Kernel/x86 - Slight cleanup to VMem code
[tpg/acess2.git] / KernelLand / Kernel / binary.c
index 5213bf2..3dab6a9 100644 (file)
@@ -31,7 +31,8 @@ extern tKernelSymbol  gKernelSymbolsEnd[];
 extern tBinaryType     gELF_Info;
 
 // === PROTOTYPES ===
- int   Binary_int_CacheArgs(const char **Path, const char ***ArgV, const char ***EnvP, void *DestBuffer);
+size_t Binary_int_CacheArgs(const char **Path, const char ***ArgV, const char ***EnvP, void *DestBuffer);
+ int   Proc_int_Execve(const char *File, const char **ArgV, const char **EnvP, int DataSize, bool bClearUser);
 tVAddr Binary_Load(const char *Path, tVAddr *EntryPoint);
 tBinary        *Binary_GetInfo(tMount MountID, tInode InodeID);
 tVAddr Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr LoadMax);
@@ -94,9 +95,10 @@ int Proc_Spawn(const char *Path)
 /**
  * \todo Document
  */
-int Binary_int_CacheArgs(const char **Path, const char ***ArgV, const char ***EnvP, void *DestBuffer)
+size_t Binary_int_CacheArgs(const char **Path, const char ***ArgV, const char ***EnvP, void *DestBuffer)
 {
-        int    size, argc=0, envc=0;
+       size_t  size;
+        int    argc=0, envc=0;
         int    i;
        char    *strbuf;
        const char      **arrays;
@@ -171,32 +173,29 @@ int Binary_int_CacheArgs(const char **Path, const char ***ArgV, const char ***En
  */
 int Proc_SysSpawn(const char *Binary, const char **ArgV, const char **EnvP, int nFD, int *FDs)
 {
-       void    *handles;
-       void    *cachebuf;
-        int    size;
-       tPID    ret;
        
        // --- Save File, ArgV and EnvP
-       size = Binary_int_CacheArgs( &Binary, &ArgV, &EnvP, NULL );
-       cachebuf = malloc( size );
+       size_t size = Binary_int_CacheArgs( &Binary, &ArgV, &EnvP, NULL );
+       void *cachebuf = malloc( size );
        Binary_int_CacheArgs( &Binary, &ArgV, &EnvP, cachebuf );
 
        // Cache the VFS handles        
-       handles = VFS_SaveHandles(nFD, FDs);
+       void *handles = VFS_SaveHandles(nFD, FDs);
 
        // Create new process   
-       ret = Proc_Clone(CLONE_VM|CLONE_NOUSER);
+       tPID ret = Proc_Clone(CLONE_VM|CLONE_NOUSER);
        if( ret == 0 )
        {
                VFS_RestoreHandles(nFD, handles);
                VFS_FreeSavedHandles(nFD, handles);
                // Frees cachebuf
-               Proc_Execve(Binary, ArgV, EnvP, size);
+               Proc_int_Execve(Binary, ArgV, EnvP, size, 0);
                for(;;);
        }
-       if( ret < 0 )
+       if( ret == -1 )
        {
                VFS_FreeSavedHandles(nFD, handles);
+               free(cachebuf);
        }
        
        return ret;
@@ -210,6 +209,11 @@ int Proc_SysSpawn(const char *Binary, const char **ArgV, const char **EnvP, int
  * \note Called Proc_ for historical reasons
  */
 int Proc_Execve(const char *File, const char **ArgV, const char **EnvP, int DataSize)
+{
+       return Proc_int_Execve(File, ArgV, EnvP, DataSize, 1);
+}
+
+int Proc_int_Execve(const char *File, const char **ArgV, const char **EnvP, int DataSize, bool bClearUser)
 {
        void    *cachebuf;
        tVAddr  entry;
@@ -235,6 +239,7 @@ int Proc_Execve(const char *File, const char **ArgV, const char **EnvP, int Data
        // --- Clear User Address space
        // NOTE: This is a little roundabout, maybe telling ClearUser to not touch the
        //       PPD area would be a better idea.
+       if( bClearUser )
        {
                 int    nfd = *Threads_GetMaxFD();
                void    *handles;
@@ -249,7 +254,7 @@ int Proc_Execve(const char *File, const char **ArgV, const char **EnvP, int Data
        base = Binary_Load(File, &entry);
        if(base == 0)
        {
-               Log_Warning("Binary", "Proc_Execve - Unable to load '%s'", File);
+               Log_Warning("Binary", "Proc_Execve - Unable to load '%s' [errno=%i]", File, errno);
                LEAVE('-');
                Threads_Exit(0, -10);
                for(;;);
@@ -406,7 +411,10 @@ tVAddr Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr Lo
                        for( i = 0; i < Binary->NumSections; i ++ )
                        {
                                tVAddr  addr = Binary->LoadSections[i].Virtual - Binary->Base + base;
-                               if( Binary_int_CheckMemFree( addr, Binary->LoadSections[i].MemSize ) )
+                               size_t  size = Binary->LoadSections[i].MemSize;
+                               if( addr + size > LoadMax )
+                                       break;
+                               if( Binary_int_CheckMemFree( addr, size ) )
                                        break;
                        }
                        // If space was found, break
@@ -425,13 +433,16 @@ tVAddr Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr Lo
        }
        
        // Map Executable In
-       fd = VFS_OpenInode(Binary->MountID, Binary->Inode, VFS_OPENFLAG_READ);
+       if( Binary->MountID )
+               fd = VFS_OpenInode(Binary->MountID, Binary->Inode, VFS_OPENFLAG_READ);
+       else
+               fd = VFS_Open(Path, VFS_OPENFLAG_READ);
        for( i = 0; i < Binary->NumSections; i ++ )
        {
                tBinarySection  *sect = &Binary->LoadSections[i];
                Uint    protflags, mapflags;
                tVAddr  addr = sect->Virtual - Binary->Base + base;
-               LOG("%i - %p to offset 0x%llx (%x)", i, addr, sect->Offset, sect->Flags);
+               LOG("%i - %p, 0x%x bytes from offset 0x%llx (%x)", i, addr, sect->FileSize, sect->Offset, sect->Flags);
 
                protflags = MMAP_PROT_READ;
                mapflags = MMAP_MAP_FIXED;
@@ -508,7 +519,14 @@ tBinary *Binary_DoLoad(tMount MountID, tInode Inode, const char *Path)
        ENTER("iMountID XInode sPath", MountID, Inode, Path);
        
        // Open File
-       fp = VFS_OpenInode(MountID, Inode, VFS_OPENFLAG_READ);
+       if( MountID )
+       {
+               fp = VFS_OpenInode(MountID, Inode, VFS_OPENFLAG_READ);
+       }
+       else
+       {
+               fp = VFS_Open(Path, VFS_OPENFLAG_READ);
+       }
        if(fp == -1) {
                LOG("Unable to load file, access denied");
                LEAVE('n');
@@ -697,6 +715,7 @@ void *Binary_LoadKernel(const char *File)
                int fd = VFS_Open(File, VFS_OPENFLAG_READ);
                tFInfo  info;
                if(fd == -1) {
+                       LOG("Opening failed");
                        LEAVE('n');
                        return NULL;
                }
@@ -704,6 +723,7 @@ void *Binary_LoadKernel(const char *File)
                mount_id = info.mount;
                inode = info.inode;
                VFS_Close(fd);
+               LOG("Mount %i, Inode %lli", mount_id, inode);
        }
        
        // Check if the binary has already been loaded
@@ -714,6 +734,7 @@ void *Binary_LoadKernel(const char *File)
                        pKBinary = pKBinary->Next )
                {
                        if(pKBinary->Info == pBinary) {
+                               LOG("Already loaded");
                                LEAVE('p', pKBinary->Base);
                                return pKBinary->Base;
                        }
@@ -728,6 +749,7 @@ void *Binary_LoadKernel(const char *File)
                return NULL;
        }
        
+       LOG("Loaded as %p", pBinary);
        // --------------
        // Now pBinary is valid (either freshly loaded or only user mapped)
        // So, map it into kernel space
@@ -736,19 +758,14 @@ void *Binary_LoadKernel(const char *File)
        // Reference Executable (Makes sure that it isn't unloaded)
        pBinary->ReferenceCount ++;
 
-       Binary_MapIn(pBinary, File, KLIB_LOWEST, KLIB_HIGHEST);
-
-       // Relocate Library
-       if( !Binary_Relocate( (void*)base ) )
-       {
-               Log_Warning("Binary", "Relocation of '%s' failed, unloading", File);
-               Binary_Unload( (void*)base );
-               Binary_Dereference( pBinary );
+       base = Binary_MapIn(pBinary, File, KLIB_LOWEST, KLIB_HIGHEST);
+       if( base == 0 ) {
                LEAVE('n');
                return 0;
        }
-       
-       // Add to list (relocator must look at itself manually, not via Binary_GetSymbol)
+
+       // Add to list
+       // TODO: Could this cause race conditions if a binary isn't fully loaded when used
        pKBinary = malloc(sizeof(*pKBinary));
        pKBinary->Base = (void*)base;
        pKBinary->Info = pBinary;
@@ -756,7 +773,7 @@ void *Binary_LoadKernel(const char *File)
        pKBinary->Next = glLoadedKernelLibs;
        glLoadedKernelLibs = pKBinary;
        SHORTREL( &glKBinListLock );
-       
+
        LEAVE('p', base);
        return (void*)base;
 }
@@ -772,7 +789,7 @@ Uint Binary_Relocate(void *Base)
        Uint32  ident = *(Uint32*) Base;
        tBinaryType     *bt = gRegBinTypes;
        
-       for(; bt; bt = bt->Next)
+       for( ; bt; bt = bt->Next)
        {
                if( (ident & bt->Mask) == (Uint)bt->Ident )
                        return bt->Relocate( (void*)Base);
@@ -806,19 +823,20 @@ int Binary_GetSymbol(const char *Name, Uint *Val)
  */
 Uint Binary_GetSymbolEx(const char *Name, Uint *Value)
 {
-        int    i;
        tKernelBin      *pKBin;
         int    numKSyms = ((Uint)&gKernelSymbolsEnd-(Uint)&gKernelSymbols)/sizeof(tKernelSymbol);
        
        // Scan Kernel
-       for( i = 0; i < numKSyms; i++ )
+       for( int i = 0; i < numKSyms; i++ )
        {
                if(strcmp(Name, gKernelSymbols[i].Name) == 0) {
+                       LOG("KSym %s = %p", gKernelSymbols[i].Name, gKernelSymbols[i].Value);
                        *Value = gKernelSymbols[i].Value;
                        return 1;
                }
        }
        
+       
        // Scan Loaded Libraries
        for(pKBin = glLoadedKernelLibs;
                pKBin;
@@ -862,15 +880,23 @@ Uint Binary_FindSymbol(void *Base, const char *Name, Uint *Val)
  */
 int Binary_int_CheckMemFree( tVAddr _start, size_t _len )
 {
+       ENTER("p_start x_len", _start, _len);
+
        _len += _start & (PAGE_SIZE-1);
        _len = (_len + PAGE_SIZE - 1) & ~(PAGE_SIZE-1);
        _start &= ~(PAGE_SIZE-1);
+       LOG("_start = %p, _len = 0x%x", _start, _len);
        for( ; _len > PAGE_SIZE; _len -= PAGE_SIZE, _start += PAGE_SIZE ) {
-               if( MM_GetPhysAddr(_start) != 0 )
+               if( MM_GetPhysAddr( (void*)_start ) != 0 ) {
+                       LEAVE('i', 1);
                        return 1;
+               }
        }
-       if( _len == PAGE_SIZE && MM_GetPhysAddr(_start) != 0 )
+       if( _len == PAGE_SIZE && MM_GetPhysAddr( (void*)_start ) != 0 ) {
+               LEAVE('i', 1);
                return 1;
+       }
+       LEAVE('i', 0);
        return 0;
 }
 

UCC git Repository :: git.ucc.asn.au