execve(2) now pushes envp to the new stack and sets up registers.

This fully implements environmental variables over exec.
This commit is contained in:
Jonas 'Sortie' Termansen 2012-04-04 01:41:29 +02:00
parent 60b9a84a51
commit 6f36ecf0b3
6 changed files with 80 additions and 15 deletions

View File

@ -29,6 +29,8 @@
.type _start, @function
_start:
movq %rcx, environ # envp
pushq %rsi
pushq %rdi

View File

@ -30,6 +30,8 @@
.type _start, @function
_start:
movl %ecx, environ # envp
# Arguments for main
push %ebx # argv
push %eax # argc

View File

@ -259,7 +259,10 @@ namespace Sortix
ResetAddressSpace();
}
int Process::Execute(const char* programname, const byte* program, size_t programsize, int argc, const char* const* argv, CPU::InterruptRegisters* regs)
int Process::Execute(const char* programname, const byte* program,
size_t programsize, int argc, const char* const* argv,
int envc, const char* const* envp,
CPU::InterruptRegisters* regs)
{
ASSERT(CurrentProcess() == this);
@ -269,10 +272,11 @@ namespace Sortix
// TODO: This may be an ugly hack!
// TODO: Move this to x86/process.cpp.
addr_t stackpos = CurrentThread()->stackpos + CurrentThread()->stacksize;
// Alright, move argv onto the new stack! First figure out exactly how
// big argv actually is.
addr_t stackpos = CurrentThread()->stackpos + CurrentThread()->stacksize;
addr_t argvpos = stackpos - sizeof(char*) * argc;
addr_t argvpos = stackpos - sizeof(char*) * (argc+1);
char** stackargv = (char**) argvpos;
size_t argvsize = 0;
@ -285,9 +289,31 @@ namespace Sortix
Maxsi::Memory::Copy(dest, argv[i], len);
}
stackpos = argvpos - argvsize;
stackargv[argc] = NULL;
ExecuteCPU(argc, stackargv, stackpos, entry, regs);
if ( argvsize % 16UL ) { argvsize += 16 - (argvsize % 16UL); }
// And then move envp onto the stack.
addr_t envppos = argvpos - argvsize - sizeof(char*) * (envc+1);
char** stackenvp = (char**) envppos;
size_t envpsize = 0;
for ( int i = 0; i < envc; i++ )
{
size_t len = String::Length(envp[i]) + 1;
envpsize += len;
char* dest = ((char*) envppos) - envpsize;
stackenvp[i] = dest;
Maxsi::Memory::Copy(dest, envp[i], len);
}
stackenvp[envc] = NULL;
if ( envpsize % 16UL ) { envpsize += 16 - (envpsize % 16UL); }
stackpos = envppos - envpsize;
ExecuteCPU(argc, stackargv, envc, stackenvp, stackpos, entry, regs);
descriptors.OnExecute();
@ -303,7 +329,9 @@ namespace Sortix
size_t count;
size_t sofar;
int argc;
int envc;
char** argv;
char** envp;
public:
SysExecVEState()
@ -315,6 +343,8 @@ namespace Sortix
sofar = 0;
argc = 0;
argv = NULL;
envc = 0;
envp = NULL;
}
~SysExecVEState()
@ -324,6 +354,8 @@ namespace Sortix
delete[] buffer;
for ( int i = 0; i < argc; i++ ) { delete[] argv[i]; }
delete[] argv;
for ( int i = 0; i < envc; i++ ) { delete[] envp[i]; }
delete[] envp;
}
};
@ -350,7 +382,10 @@ namespace Sortix
{
CPU::InterruptRegisters* regs = Syscall::InterruptRegs();
Process* process = CurrentProcess();
int result = process->Execute(state->filename, state->buffer, state->count, state->argc, state->argv, regs);
int result = process->Execute(state->filename, state->buffer,
state->count, state->argc,
state->argv, state->envc,
state->envp, regs);
if ( result == 0 ) { Syscall::AsIs(); }
delete state;
return result;
@ -391,7 +426,7 @@ namespace Sortix
return (DevBuffer*) dev;
}
int SysExecVE(const char* filename, char* const argv[], char* const /*envp*/[])
int SysExecVE(const char* filename, char* const argv[], char* const envp[])
{
// TODO: Validate that all the pointer-y parameters are SAFE!
@ -404,12 +439,13 @@ namespace Sortix
state->filename = String::Clone(filename);
if ( !state->filename ) { delete state; return -1; }
int argc; for ( argc = 0; argv[argc]; argc++ );
int argc; for ( argc = 0; argv && argv[argc]; argc++ );
int envc; for ( envc = 0; envp && envp[envc]; envc++ );
state->argc = argc;
state->argv = new char*[state->argc];
Maxsi::Memory::Set(state->argv, 0, sizeof(char*) * state->argc);
state->argv = new char*[argc+1];
if ( !state->argv ) { delete state; return -1; }
state->argc = argc;
Maxsi::Memory::Set(state->argv, 0, sizeof(char*) * (state->argc+1));
for ( int i = 0; i < state->argc; i++ )
{
@ -417,6 +453,17 @@ namespace Sortix
if ( !state->argv[i] ) { delete state; return -1; }
}
state->envp = new char*[envc+1];
if ( !state->envp ) { delete state; return -1; }
state->envc = envc;
Maxsi::Memory::Set(state->envp, 0, sizeof(char*) * (state->envc+1));
for ( int i = 0; i < state->envc; i++ )
{
state->envp[i] = String::Clone(envp[i]);
if ( !state->envp[i] ) { delete state; return -1; }
}
Process* process = CurrentProcess();
state->dev = OpenProgramImage(state->filename, process->workingdir, "/bin");
if ( !state->dev ) { delete state; return -1; }

View File

@ -96,7 +96,10 @@ namespace Sortix
bool sigint;
public:
int Execute(const char* programname, const byte* program, size_t programsize, int argc, const char* const* argv, CPU::InterruptRegisters* regs);
int Execute(const char* programname, const byte* program,
size_t programsize, int argc, const char* const* argv,
int envc, const char* const* envp,
CPU::InterruptRegisters* regs);
void ResetAddressSpace();
void Exit(int status);
@ -108,7 +111,9 @@ namespace Sortix
private:
Thread* ForkThreads(Process* processclone);
void ExecuteCPU(int argc, char** argv, addr_t stackpos, addr_t entry, CPU::InterruptRegisters* regs);
void ExecuteCPU(int argc, char** argv, int envc, char** envp,
addr_t stackpos, addr_t entry,
CPU::InterruptRegisters* regs);
public:
void ResetForExecute();

View File

@ -27,10 +27,14 @@
namespace Sortix
{
void Process::ExecuteCPU(int argc, char** argv, addr_t stackpos, addr_t entry, CPU::InterruptRegisters* regs)
void Process::ExecuteCPU(int argc, char** argv, int envc, char** envp,
addr_t stackpos, addr_t entry,
CPU::InterruptRegisters* regs)
{
regs->rdi = argc;
regs->rsi = (size_t) argv;
regs->rdx = envc;
regs->rcx = (size_t) envp;
regs->rip = entry;
regs->userrsp = stackpos & ~(15UL);
regs->rbp = stackpos;

View File

@ -27,10 +27,15 @@
namespace Sortix
{
void Process::ExecuteCPU(int argc, char** argv, addr_t stackpos, addr_t entry, CPU::InterruptRegisters* regs)
void Process::ExecuteCPU(int argc, char** argv, int envc, char** envp,
addr_t stackpos, addr_t entry,
CPU::InterruptRegisters* regs)
{
regs->eax = argc;
regs->ebx = (size_t) argv;
regs->edx = envc;
regs->ecx = (size_t) envp;
regs->eip = entry;
regs->useresp = stackpos;
regs->ebp = stackpos;