X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fbinary.c;h=5170dac06ccda9de159b0f49ac54f3795d31781c;hb=b6e856e1570c371b7002f1a93a1ea0e978ffdab6;hp=5213bf2d50cd203a4e44df153509f478f74e4d75;hpb=48743e39650eb1ef988380e9d95f27fd40d3a9ce;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/binary.c b/KernelLand/Kernel/binary.c index 5213bf2d..5170dac0 100644 --- a/KernelLand/Kernel/binary.c +++ b/KernelLand/Kernel/binary.c @@ -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; @@ -227,29 +231,26 @@ int Proc_Execve(const char *File, const char **ArgV, const char **EnvP, int Data } // --- Get argc - for( argc = 0; ArgV && ArgV[argc]; argc ++ ); + for( argc = 0; ArgV && ArgV[argc]; argc ++ ) + ; // --- Set Process Name Threads_SetName(File); // --- 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; - handles = VFS_SaveHandles(nfd, NULL); - VFS_CloseAllUserHandles(); + // MM_ClearUser should preserve handles MM_ClearUser(); - VFS_RestoreHandles(nfd, handles); - VFS_FreeSavedHandles(nfd, handles); + // - NOTE: Not a reliable test, but helps for now + ASSERTC( VFS_IOCtl(0, 0, NULL), !=, -1 ); } // --- Load new binary 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(;;); @@ -329,6 +330,8 @@ tVAddr Binary_Load(const char *Path, tVAddr *EntryPoint) if(pBinary->Interpreter) { tVAddr start; if( Binary_Load(pBinary->Interpreter, &start) == 0 ) { + Log_Error("Binary", "Can't load interpeter '%s' for '%s'", + pBinary->Interpreter, Path); LEAVE('x', 0); return 0; } @@ -406,7 +409,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 +431,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 +517,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 +713,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 +721,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 +732,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 +747,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 +756,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 +771,7 @@ void *Binary_LoadKernel(const char *File) pKBinary->Next = glLoadedKernelLibs; glLoadedKernelLibs = pKBinary; SHORTREL( &glKBinListLock ); - + LEAVE('p', base); return (void*)base; } @@ -772,7 +787,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 +821,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 +878,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; }