exec.c

Go to the documentation of this file.
00001 /*****************************************************************************************
00002  Copyright (c) 2002-2004 The UbixOS Project
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are
00006  permitted provided that the following conditions are met:
00007 
00008  Redistributions of source code must retain the above copyright notice, this list of
00009  conditions, the following disclaimer and the list of authors.  Redistributions in binary
00010  form must reproduce the above copyright notice, this list of conditions, the following
00011  disclaimer and the list of authors in the documentation and/or other materials provided
00012  with the distribution. Neither the name of the UbixOS Project nor the names of its
00013  contributors may be used to endorse or promote products derived from this software
00014  without specific prior written permission.
00015 
00016  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
00017  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00018  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
00019  THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00020  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00021  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00022  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
00023  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00024  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025 
00026  $Id$
00027 
00028 *****************************************************************************************/
00029 
00030 #include <ubixos/exec.h>
00031 #include <ubixos/sched.h>
00032 #include <ubixos/ld.h>
00033 #include <ubixos/kpanic.h>
00034 #include <ubixos/endtask.h>
00035 #include <vmm/vmm.h>
00036 #include <lib/kmalloc.h>
00037 #include <lib/kprintf.h>
00038 #include <lib/string.h>
00039 #include <assert.h>
00040 
00041 #define STACK_ADDR 0xC800000
00042 
00043 /*****************************************************************************************
00044 
00045  Function:   execThread(void (*)(void),int,char *);
00046  Description: This function will create a thread from code in the current memory space
00047 
00048  Notes:
00049  
00050  05/19/04 - This does not work the way I want it to it still makes a copy of kernel space
00051             so do not use out side of kernel space
00052 
00053 *****************************************************************************************/
00054 uInt32 execThread(void (* tproc)(void),uInt32 stack,char *arg) {
00055   kTask_t * newProcess = 0x0;
00056   /* Find A New Thread */
00057   newProcess = schedNewTask();
00058   assert(newProcess); 
00059   if (stack < 0x100000)
00060     kpanic("exec: stack not in valid area: [0x%X]\n",stack);
00061 
00062   /* Set All The Correct Thread Attributes */
00063   newProcess->tss.back_link    = 0x0;
00064   newProcess->tss.esp0         = 0x0;
00065   newProcess->tss.ss0          = 0x0;
00066   newProcess->tss.esp1         = 0x0;
00067   newProcess->tss.ss1          = 0x0;
00068   newProcess->tss.esp2         = 0x0;
00069   newProcess->tss.ss2          = 0x0;
00070   newProcess->tss.cr3          = (unsigned int)kernelPageDirectory;
00071   newProcess->tss.eip          = (unsigned int)tproc;
00072   newProcess->tss.eflags       = 0x206;
00073   newProcess->tss.esp          = stack;
00074   newProcess->tss.ebp          = stack;
00075   newProcess->tss.esi          = 0x0;
00076   newProcess->tss.edi          = 0x0;
00077 
00078   /* Set these up to be ring 3 tasks */
00079   /*
00080   newProcess->tss.es           = 0x30+3;
00081   newProcess->tss.cs           = 0x28+3;
00082   newProcess->tss.ss           = 0x30+3;
00083   newProcess->tss.ds           = 0x30+3;
00084   newProcess->tss.fs           = 0x30+3;
00085   newProcess->tss.gs           = 0x30+3;
00086   */
00087 
00088   newProcess->tss.es           = 0x10;
00089   newProcess->tss.cs           = 0x08;
00090   newProcess->tss.ss           = 0x10;
00091   newProcess->tss.ds           = 0x10;
00092   newProcess->tss.fs           = 0x10;
00093   newProcess->tss.gs           = 0x10;
00094 
00095   newProcess->tss.ldt          = 0x18;
00096   newProcess->tss.trace_bitmap = 0x0000;
00097   newProcess->tss.io_map       = 0x8000;
00098   newProcess->oInfo.vmStart    = 0x6400000;
00099   
00100   newProcess->imageFd          = 0x0;
00101 
00102   /* Set up default stack for thread here filled with arg list 3 times */
00103   asm volatile(
00104     "pusha               \n"
00105     "movl   %%esp,%%ecx  \n"
00106     "movl   %1,%%eax     \n"
00107     "movl   %%eax,%%esp  \n"
00108     "pushl  %%ebx        \n"
00109     "pushl  %%ebx        \n"
00110     "pushl  %%ebx        \n"
00111     "movl   %%esp,%%eax  \n"
00112     "movl   %%eax,%1     \n"
00113     "movl   %%ecx,%%esp  \n"
00114     "popa                \n"
00115     :
00116     : "b" (arg),"m" (newProcess->tss.esp)
00117     );
00118 
00119   /* Put new thread into the READY state */
00120   sched_setStatus(newProcess->id,READY);
00121 
00122   /* Return with the new process ID */
00123   return((uInt32)newProcess);
00124   }
00125 
00126 /*****************************************************************************************
00127 
00128  Function: void execFile(char *file);
00129  Description: This Function Executes A Kile Into A New VM Space With Out
00130               Having To Fork
00131  Notes:
00132 
00133  07/30/02 - I Have Made Some Heavy Changes To This As Well As Fixed A Few
00134             Memory Leaks The Memory Allocated To Load The Binary Into Is
00135             Now Unmapped So It Can Be Used Again And Not Held Onto Until
00136             The Program Exits
00137 
00138  07/30/02 - Now I Have To Make A Better Memory Allocator So We Can Set Up
00139             The Freshly Allocated Pages With The Correct Permissions
00140 
00141 *****************************************************************************************/
00142 void execFile(char *file,int argc,char **argv,int console) {
00143 
00144   int        i         = 0x0;
00145   int        x         = 0x0;
00146   u_int32_t *tmp       = 0x0;
00147 
00148   fileDescriptor   *tmpFd         = 0x0;
00149   elfHeader        *binaryHeader  = 0x0;
00150   elfProgramHeader *programHeader = 0x0;
00151 
00152   /* Get A New Task For This Proccess */
00153   _current = schedNewTask();
00154   assert(_current);
00155   _current->gid  = 0x0;
00156   _current->uid  = 0x0;
00157   _current->term = tty_find(console);
00158   if (_current->term == 0x0)
00159     kprintf("Error: invalid console\n");
00160 
00161   /* Set tty ownership */
00162   _current->term->owner = _current->id;
00163 
00164   /* Now We Must Create A Virtual Space For This Proccess To Run In */
00165   _current->tss.cr3 = (uInt32)vmmCreateVirtualSpace(_current->id);
00166 
00167   /* To Better Load This Application We Will Switch Over To Its VM Space */
00168   asm volatile(
00169     "movl %0,%%eax          \n"
00170     "movl %%eax,%%cr3       \n"
00171     : : "d" ((uInt32 *)(_current->tss.cr3))
00172     );
00173 
00174   /* Lets Find The File */
00175   tmpFd = fopen(file,"r");
00176 
00177   /* If We Dont Find the File Return */
00178   if (tmpFd == 0x0) {
00179     kprintf("Exec Format Error: Binary File Not Executable.\n");
00180     fclose(tmpFd);
00181     return;
00182     }
00183   if (tmpFd->perms == 0x0) {
00184     kprintf("Exec Format Error: Binary File Not Executable.\n");
00185     fclose(tmpFd);
00186     return;
00187     }
00188 
00189   /* Load ELF Header */
00190   binaryHeader = (elfHeader *)kmalloc(sizeof(elfHeader));
00191 
00192 
00193   //kprintf(">a:%i:0x%X:0x%X<",sizeof(elfHeader),binaryHeader,tmpFd);
00194   fread(binaryHeader,sizeof(elfHeader),1,tmpFd);
00195 
00196 
00197   /* Check If App Is A Real Application */
00198   if ((binaryHeader->eIdent[1] != 'E') && (binaryHeader->eIdent[2] != 'L') && (binaryHeader->eIdent[3] != 'F')) {
00199     kprintf("Exec Format Error: Binary File Not Executable.\n");
00200     kfree(binaryHeader);
00201     fclose(tmpFd);
00202     return;
00203     }
00204   else if (binaryHeader->eType != 2) {
00205     kprintf("Exec Format Error: Binary File Not Executable.\n");
00206     kfree(binaryHeader);
00207     fclose(tmpFd);
00208     return;
00209     }
00210   else if (binaryHeader->eEntry == 0x300000) {
00211     kprintf("Exec Format Error: Binary File Not Executable.\n");
00212     kfree(binaryHeader);
00213     fclose(tmpFd);
00214     return;
00215     }
00216 
00217   /* Load The Program Header(s) */
00218   programHeader = (elfProgramHeader *)kmalloc(sizeof(elfProgramHeader)*binaryHeader->ePhnum);
00219   fseek(tmpFd,binaryHeader->ePhoff,0);
00220 
00221   //kprintf(">c:%i:0x%X:0x%X<",sizeof(elfProgramHeader)*binaryHeader->ePhnum,programHeader,tmpFd);
00222   fread(programHeader,(sizeof(elfProgramHeader)*binaryHeader->ePhnum),1,tmpFd);
00223   //kprintf(">d<");
00224 
00225   /* Loop Through The Header And Load Sections Which Need To Be Loaded */
00226   for (i=0;i<binaryHeader->ePhnum;i++) {
00227     if (programHeader[i].phType == 1) {
00228       /*
00229       Allocate Memory Im Going To Have To Make This Load Memory With Correct
00230       Settings so it helps us in the future
00231       */
00232       for (x = 0x0;x < (programHeader[i].phMemsz);x += 0x1000) {
00233         /* Make readonly and read/write !!! */
00234         if (vmm_remapPage(vmmFindFreePage(_current->id),((programHeader[i].phVaddr & 0xFFFFF000) + x),PAGE_DEFAULT) == 0x0)
00235           K_PANIC("Remap Page Failed");
00236 
00237         memset((void *)((programHeader[i].phVaddr & 0xFFFFF000) + x),0x0,0x1000);
00238         }
00239       _current->oInfo.vmStart = 0x80000000;
00240       _current->td.vm_daddr = (char *)(programHeader[i].phVaddr & 0xFFFFF000);
00241       /* Now Load Section To Memory */
00242       fseek(tmpFd,programHeader[i].phOffset,0);
00243       fread((void *)programHeader[i].phVaddr,programHeader[i].phFilesz,1,tmpFd);
00244       if ((programHeader[i].phFlags & 0x2) != 0x2) {
00245         kprintf("pH: [0x%X]\n",programHeader[i].phMemsz);
00246         for (x = 0x0;x < (programHeader[i].phMemsz);x += 0x1000) {
00247           if ((vmm_setPageAttributes((programHeader[i].phVaddr & 0xFFFFF000) + x,PAGE_PRESENT | PAGE_USER)) != 0x0)
00248             kpanic("Error: vmm_setPageAttributes failed, File: %s, Line: %i\n",__FILE__,__LINE__);
00249           }
00250         }
00251       }
00252     }
00253 
00254   /* Set Virtual Memory Start */
00255   _current->oInfo.vmStart = 0x80000000;
00256   _current->td.vm_daddr = (char *)(programHeader[i].phVaddr & 0xFFFFF000);
00257 
00258   /* Set Up Stack Space */
00259   for (x = 1;x < 100;x++) {
00260     vmm_remapPage(vmmFindFreePage(_current->id),STACK_ADDR - (x * 0x1000),PAGE_DEFAULT | PAGE_STACK);
00261     }
00262 
00263   /* Kernel Stack 0x2000 bytes long */
00264   vmm_remapPage(vmmFindFreePage(_current->id),0x5BC000,KERNEL_PAGE_DEFAULT | PAGE_STACK);
00265   vmm_remapPage(vmmFindFreePage(_current->id),0x5BB000,KERNEL_PAGE_DEFAULT | PAGE_STACK);
00266 
00267   /* Set All The Proper Information For The Task */
00268   _current->tss.back_link    = 0x0;
00269   _current->tss.esp0         = 0x5BC000;
00270   _current->tss.ss0          = 0x10;
00271   _current->tss.esp1         = 0x0;
00272   _current->tss.ss1          = 0x0;
00273   _current->tss.esp2         = 0x0;
00274   _current->tss.ss2          = 0x0;
00275   _current->tss.eip          = (long)binaryHeader->eEntry;
00276   _current->tss.eflags       = 0x206;
00277   _current->tss.esp          = STACK_ADDR - 12;
00278   _current->tss.ebp          = STACK_ADDR;
00279   _current->tss.esi          = 0x0;
00280   _current->tss.edi          = 0x0;
00281 
00282   /* Set these up to be ring 3 tasks */
00283   _current->tss.es           = 0x30+3;
00284   _current->tss.cs           = 0x28+3;
00285   _current->tss.ss           = 0x30+3;
00286   _current->tss.ds           = 0x30+3;
00287   _current->tss.fs           = 0x30+3;
00288   _current->tss.gs           = 0x30+3;
00289 
00290   _current->tss.ldt          = 0x18;
00291   _current->tss.trace_bitmap = 0x0000;
00292   _current->tss.io_map       = 0x8000;
00293 
00294   sched_setStatus(_current->id,READY);
00295 
00296   kfree(binaryHeader);
00297   kfree(programHeader);
00298   fclose(tmpFd);
00299 
00300   tmp = (uInt32 *)_current->tss.esp0 - 5;
00301   tmp[0] = binaryHeader->eEntry;
00302   tmp[3] = STACK_ADDR - 12;
00303 
00304   tmp = (uInt32 *)STACK_ADDR - 2;
00305 
00306   if (_current->id > 4)
00307   kprintf("argv[0]: [%s]\n",argv[0]);
00308   kprintf("argv: [0x%X]\n",argv);
00309   tmp[0] = (u_int32_t)argv;
00310   tmp[1] = (u_int32_t)argv;
00311 
00312 
00313   /* Switch Back To The Kernels VM Space */
00314   asm volatile(
00315     "movl %0,%%eax          \n"
00316     "movl %%eax,%%cr3       \n"
00317     : : "d" ((uInt32 *)(kernelPageDirectory))
00318     );
00319 
00320   /* Finally Return */
00321   return;
00322   }
00323 
00324 /*****************************************************************************************
00325 
00326  Function: void sysExec();
00327  Description: This Is The System Call To Execute A New Task
00328 
00329  Notes:
00330  04-22-03 - It Now Loads Sections Not The Full File
00331 
00332 *****************************************************************************************/
00333 void sysExec(char *file,int argc,char **argv) {
00334   int     i           = 0x0;
00335   int     x           = 0x0;
00336   uInt32 *tmp         = 0x0;
00337   uInt32  ldAddr      = 0x0;
00338   uInt32  seg_size    = 0x0;
00339   uInt32  seg_addr    = 0x0;
00340   char   *interp      = 0x0;
00341 
00342   fileDescriptor   *tmpFd         = 0x0;
00343   elfHeader        *binaryHeader  = 0x0;
00344   elfProgramHeader *programHeader = 0x0;
00345   elfSectionHeader *sectionHeader = 0x0;
00346   elfDynamic       *elfDynamicS   = 0x0;
00347 
00348   tmpFd = fopen(file,"r");
00349   _current->imageFd = tmpFd;
00350   /* If We Dont Find the File Return */
00351   if (tmpFd == 0x0) {
00352     return;
00353     }
00354   if (tmpFd->perms == 0) {
00355     kprintf("Exec Format Error: Binary File Not Executable.\n");
00356     fclose(tmpFd);
00357     return;
00358     }
00359 
00360   /* Load ELF Header */
00361 
00362   if ((binaryHeader = (elfHeader *)kmalloc(sizeof(elfHeader))) == 0x0) 
00363     endTask(_current->id);
00364     fread(binaryHeader,sizeof(elfHeader),1,tmpFd);
00365     /* Set sectionHeader To Point To Loaded Binary To We Can Gather Info */
00366 
00367   /* Check If App Is A Real Application */
00368   if ((binaryHeader->eIdent[1] != 'E') && (binaryHeader->eIdent[2] != 'L') && (binaryHeader->eIdent[3] != 'F')) {
00369     kprintf("Exec Format Error: Binary File Not Executable.\n");
00370     kfree(binaryHeader);
00371     fclose(tmpFd);
00372 
00373     return;
00374     }
00375   else if (binaryHeader->eType != 2) {
00376     kprintf("Exec Format Error: Binary File Not Executable.\n");
00377     kfree(binaryHeader);
00378     fclose(tmpFd);
00379     return;
00380     }
00381   else if (binaryHeader->eEntry == 0x300000) {
00382     kprintf("Exec Format Error: Binary File Not Executable.\n");
00383     kfree(binaryHeader);
00384     fclose(tmpFd);
00385     return;
00386     }
00387 
00388   /* Load The Program Header(s) */
00389   if ((programHeader = (elfProgramHeader *)kmalloc(sizeof(elfProgramHeader)*binaryHeader->ePhnum)) == 0x0)
00390     endTask(_current->id);
00391 
00392   assert(programHeader);
00393   fseek(tmpFd,binaryHeader->ePhoff,0);
00394   fread(programHeader,(sizeof(elfProgramHeader)*binaryHeader->ePhnum),1,tmpFd);
00395 
00396   if ((sectionHeader = (elfSectionHeader *)kmalloc(sizeof(elfSectionHeader)*binaryHeader->eShnum)) == 0x0)
00397     endTask(_current->id);
00398 
00399   assert(sectionHeader);
00400   fseek(tmpFd,binaryHeader->eShoff,0);
00401   fread(sectionHeader,sizeof(elfSectionHeader)*binaryHeader->eShnum,1,tmpFd);
00402 
00403   /* Loop Through The Header And Load Sections Which Need To Be Loaded */
00404   for (i=0;i<binaryHeader->ePhnum;i++) {
00405     switch (programHeader[i].phType) {
00406       case PT_LOAD:
00407         seg_addr = trunc_page(programHeader[i].phVaddr);
00408         seg_size = round_page(programHeader[i].phMemsz + programHeader[i].phVaddr - seg_addr);
00409 
00410         /*
00411         Allocate Memory Im Going To Have To Make This Load Memory With Correct
00412         Settings so it helps us in the future
00413         */
00414         for (x = 0x0;x < (programHeader[i].phMemsz);x += 0x1000) {
00415           /* Make readonly and read/write !!! */
00416           if (vmm_remapPage(vmmFindFreePage(_current->id),((programHeader[i].phVaddr & 0xFFFFF000) + x),PAGE_DEFAULT) == 0x0)
00417             K_PANIC("Error: Remap Page Failed");
00418           memset((void *)((programHeader[i].phVaddr & 0xFFFFF000) + x),0x0,0x1000);
00419           }
00420 
00421         /* Now Load Section To Memory */
00422         fseek(tmpFd,programHeader[i].phOffset,0);
00423         fread((void *)programHeader[i].phVaddr,programHeader[i].phFilesz,1,tmpFd);
00424         if ((programHeader[i].phFlags & 0x2) != 0x2) {
00425           for (x = 0x0;x < (programHeader[i].phMemsz);x += 0x1000) {
00426             if ((vmm_setPageAttributes((programHeader[i].phVaddr & 0xFFFFF000) + x,PAGE_PRESENT | PAGE_USER)) != 0x0)
00427               kpanic("Error: vmm_setPageAttributes failed, File: %s,Line: %i\n",__FILE__,__LINE__);
00428             }
00429           }
00430         kprintf("setting daddr\n");
00431         if (binaryHeader->eEntry >= programHeader[i].phVaddr && binaryHeader->eEntry < (programHeader[i].phVaddr + programHeader[i].phMemsz)) {
00432           /* We're suposed to do something here? */
00433           }
00434         else {
00435           _current->td.vm_dsize = seg_size >> PAGE_SHIFT;
00436           _current->td.vm_daddr = (char *)seg_addr;
00437           }
00438 
00439         _current->oInfo.vmStart = ((programHeader[i].phVaddr & 0xFFFFF000) + 0xA900000);
00440         break;
00441       case PT_DYNAMIC:
00442         //newLoc = (char *)programHeader[i].phVaddr;
00443         elfDynamicS = (elfDynamic *)programHeader[i].phVaddr;
00444         fseek(tmpFd,programHeader[i].phOffset,0);
00445         fread((void *)programHeader[i].phVaddr,programHeader[i].phFilesz,1,tmpFd);
00446         break;
00447       case PT_INTERP:
00448         interp = (char *)kmalloc(programHeader[i].phFilesz);
00449         fseek(tmpFd,programHeader[i].phOffset,0);
00450         fread((void *)interp,programHeader[i].phFilesz,1,tmpFd);
00451         kprintf("Interp: [%s]\n",interp);
00452         ldAddr = ldEnable();
00453         break;
00454       default:
00455         break;
00456       }
00457     }
00458 
00459   /* What is this doing? 11/23/06 */
00460   if (elfDynamicS != 0x0) {
00461     for (i=0;i<12;i++) {
00462       if (elfDynamicS[i].dynVal == 0x3) {
00463         tmp = (uInt32 *)elfDynamicS[i].dynPtr;
00464         if (tmp == 0x0)
00465           kpanic("tmp: NULL\n");
00466         tmp[2] = (uInt32)ldAddr;
00467         tmp[1] = (uInt32)tmpFd;
00468         break;
00469         }
00470       }
00471     }
00472           _current->td.vm_dsize = seg_size >> PAGE_SHIFT;
00473           _current->td.vm_daddr = (char *)seg_addr;
00474 
00475   vmm_cleanVirtualSpace(_current->td.vm_daddr + (_current->td.vm_dsize << PAGE_SIZE));
00476 
00477   /* Adjust iframe */
00478   tmp = (uInt32 *)_current->tss.esp0 - 5;
00479   tmp[0] = binaryHeader->eEntry;
00480   tmp[3] = STACK_ADDR - 12;
00481 
00482   tmp = (uInt32 *)STACK_ADDR - 2;
00483   kprintf("argv: [0x%X]\n",argv);
00484   tmp[0] = (u_int32_t)argv;
00485   tmp[1] = (u_int32_t)argv;
00486 
00487  /* Now That We Relocated The Binary We Can Unmap And Free Header Info */
00488   kfree(binaryHeader);
00489   kfree(programHeader);
00490 
00491   return;
00492   }
00493 
00494 /***
00495  END
00496  ***/

Generated on Tue Dec 5 23:34:57 2006 for UbixOS V2 by  doxygen 1.4.7