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);
/**
* \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;
*/
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;
* \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;
}
// --- 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(;;);
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;
}
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
}
// 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;
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');
int fd = VFS_Open(File, VFS_OPENFLAG_READ);
tFInfo info;
if(fd == -1) {
+ LOG("Opening failed");
LEAVE('n');
return NULL;
}
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
pKBinary = pKBinary->Next )
{
if(pKBinary->Info == pBinary) {
+ LOG("Already loaded");
LEAVE('p', pKBinary->Base);
return pKBinary->Base;
}
return NULL;
}
+ LOG("Loaded as %p", pBinary);
// --------------
// Now pBinary is valid (either freshly loaded or only user mapped)
// So, map it into kernel space
// 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;
pKBinary->Next = glLoadedKernelLibs;
glLoadedKernelLibs = pKBinary;
SHORTREL( &glKBinListLock );
-
+
LEAVE('p', base);
return (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);
*/
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;
*/
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;
}