From 6d3e12899b8b0a3ddc6062fc43b18cba0c788920 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 22 Feb 2019 01:55:22 +0100 Subject: [PATCH] Kernel: Pass process arguments directly on the stack. Get rid of the convoluted get_arguments and get_environment syscalls. This patch also adds a simple /bin/env that just prints its environment. --- Kernel/Process.cpp | 84 +++++++++++++++++++++------------------------ Kernel/Process.h | 4 --- Kernel/Syscall.cpp | 4 --- Kernel/Syscall.h | 2 -- Kernel/sync.sh | 1 + LibC/entry.cpp | 15 ++------ Userland/.gitignore | 1 + Userland/Makefile | 5 +++ Userland/env.cpp | 9 +++++ 9 files changed, 59 insertions(+), 66 deletions(-) create mode 100644 Userland/env.cpp diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index fc7e27a1c0..b2ab82d6e3 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -223,9 +223,6 @@ Process* Process::fork(RegisterDump& regs) dbgprintf("fork: child=%p\n", child); #endif - child->m_initial_arguments = m_initial_arguments; - child->m_initial_environment = m_initial_environment; - for (auto& region : m_regions) { #ifdef FORK_DEBUG dbgprintf("fork: cloning Region{%p} \"%s\" L%x\n", region.ptr(), region->name.characters(), region->laddr().get()); @@ -426,8 +423,46 @@ void Process::make_userspace_stack(Vector arguments, Vector envi m_stack_top3 = region->laddr().offset(default_userspace_stack_size).get(); m_tss.esp = m_stack_top3; - m_initial_arguments = move(arguments); - m_initial_environment = move(environment); + char* stack_base = (char*)region->laddr().get(); + int argc = arguments.size(); + char** argv = (char**)stack_base; + char** env = argv + arguments.size() + 1; + char* bufptr = stack_base + (sizeof(char*) * (arguments.size() + 1)) + (sizeof(char*) * (environment.size() + 1)); + + size_t total_blob_size = 0; + for (auto& a : arguments) + total_blob_size += a.length() + 1; + for (auto& e : environment) + total_blob_size += e.length() + 1; + + size_t total_meta_size = sizeof(char*) * (arguments.size() + 1) + sizeof(char*) * (environment.size() + 1); + + // FIXME: It would be better if this didn't make us panic. + ASSERT((total_blob_size + total_meta_size) < default_userspace_stack_size); + + for (size_t i = 0; i < arguments.size(); ++i) { + argv[i] = bufptr; + memcpy(bufptr, arguments[i].characters(), arguments[i].length()); + bufptr += arguments[i].length(); + *(bufptr++) = '\0'; + printf("argv[%u] = %p (%s)\n", i, argv[i], argv[i]); + } + argv[arguments.size()] = nullptr; + + for (size_t i = 0; i < environment.size(); ++i) { + env[i] = bufptr; + memcpy(bufptr, environment[i].characters(), environment[i].length()); + bufptr += environment[i].length(); + *(bufptr++) = '\0'; + printf("env[%u] = %p (%s)\n", i, env[i], env[i]); + } + env[environment.size()] = nullptr; + + // NOTE: The stack needs to be 16-byte aligned. + push_value_on_stack((dword)env); + push_value_on_stack((dword)argv); + push_value_on_stack((dword)argc); + push_value_on_stack(0); } int Process::exec(String path, Vector arguments, Vector environment) @@ -529,45 +564,6 @@ Process* Process::create_user_process(const String& path, uid_t uid, gid_t gid, return process; } -int Process::sys$get_environment(char*** environ) -{ - auto* region = allocate_region(LinearAddress(), PAGE_SIZE, "environ"); - if (!region) - return -ENOMEM; - MM.map_region(*this, *region); - char* envpage = (char*)region->laddr().get(); - *environ = (char**)envpage; - char* bufptr = envpage + (sizeof(char*) * (m_initial_environment.size() + 1)); - for (size_t i = 0; i < m_initial_environment.size(); ++i) { - (*environ)[i] = bufptr; - memcpy(bufptr, m_initial_environment[i].characters(), m_initial_environment[i].length()); - bufptr += m_initial_environment[i].length(); - *(bufptr++) = '\0'; - } - (*environ)[m_initial_environment.size()] = nullptr; - return 0; -} - -int Process::sys$get_arguments(int* argc, char*** argv) -{ - auto* region = allocate_region(LinearAddress(), PAGE_SIZE, "argv"); - if (!region) - return -ENOMEM; - MM.map_region(*this, *region); - char* argpage = (char*)region->laddr().get(); - *argc = m_initial_arguments.size(); - *argv = (char**)argpage; - char* bufptr = argpage + (sizeof(char*) * (m_initial_arguments.size() + 1)); - for (size_t i = 0; i < m_initial_arguments.size(); ++i) { - (*argv)[i] = bufptr; - memcpy(bufptr, m_initial_arguments[i].characters(), m_initial_arguments[i].length()); - bufptr += m_initial_arguments[i].length(); - *(bufptr++) = '\0'; - } - (*argv)[m_initial_arguments.size()] = nullptr; - return 0; -} - Process* Process::create_kernel_process(String&& name, void (*e)()) { auto* process = new Process(move(name), (uid_t)0, (gid_t)0, (pid_t)0, Ring0); diff --git a/Kernel/Process.h b/Kernel/Process.h index b95c633506..c6d2bbb03f 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -183,8 +183,6 @@ public: int sys$usleep(useconds_t usec); int sys$gettimeofday(timeval*); int sys$gethostname(char* name, size_t length); - int sys$get_arguments(int* argc, char*** argv); - int sys$get_environment(char*** environ); int sys$uname(utsname*); int sys$readlink(const char*, char*, size_t); int sys$ttyname_r(int fd, char*, size_t); @@ -386,8 +384,6 @@ private: static void notify_waiters(pid_t waitee, int exit_status, int signal); - Vector m_initial_arguments; - Vector m_initial_environment; HashTable m_gids; Region* m_signal_stack_user_region { nullptr }; diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index f47ae4d644..2e7a4bf740 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -111,10 +111,6 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, current->sys$exit((int)arg1); ASSERT_NOT_REACHED(); return 0; - case Syscall::SC_get_arguments: - return current->sys$get_arguments((int*)arg1, (char***)arg2); - case Syscall::SC_get_environment: - return current->sys$get_environment((char***)arg1); case Syscall::SC_chdir: return current->sys$chdir((const char*)arg1); case Syscall::SC_uname: diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 9eaacab358..730eb9b923 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -23,7 +23,6 @@ __ENUMERATE_SYSCALL(getcwd) \ __ENUMERATE_SYSCALL(gettimeofday) \ __ENUMERATE_SYSCALL(gethostname) \ - __ENUMERATE_SYSCALL(get_arguments) \ __ENUMERATE_SYSCALL(chdir) \ __ENUMERATE_SYSCALL(uname) \ __ENUMERATE_SYSCALL(set_mmap_name) \ @@ -31,7 +30,6 @@ __ENUMERATE_SYSCALL(write) \ __ENUMERATE_SYSCALL(ttyname_r) \ __ENUMERATE_SYSCALL(stat) \ - __ENUMERATE_SYSCALL(get_environment) \ __ENUMERATE_SYSCALL(getsid) \ __ENUMERATE_SYSCALL(setsid) \ __ENUMERATE_SYSCALL(getpgid) \ diff --git a/Kernel/sync.sh b/Kernel/sync.sh index 1328ad7ba3..f7e05744fc 100755 --- a/Kernel/sync.sh +++ b/Kernel/sync.sh @@ -69,6 +69,7 @@ cp -v ../Userland/top mnt/bin/top cp -v ../Userland/ln mnt/bin/ln cp -v ../Userland/df mnt/bin/df cp -v ../Userland/su mnt/bin/su +cp -v ../Userland/env mnt/bin/env chmod 4755 mnt/bin/su cp -v ../Applications/Terminal/Terminal mnt/bin/Terminal cp -v ../Applications/FontEditor/FontEditor mnt/bin/FontEditor diff --git a/LibC/entry.cpp b/LibC/entry.cpp index 591c85a969..9446445d91 100644 --- a/LibC/entry.cpp +++ b/LibC/entry.cpp @@ -13,28 +13,19 @@ char** environ; void __malloc_init(); void __stdio_init(); -int _start() +int _start(int argc, char** argv, char** env) { errno = 0; + environ = env; __stdio_init(); __malloc_init(); - int status = 254; - int argc; - char** argv; - int rc = syscall(SC_get_arguments, &argc, &argv); - if (rc < 0) - goto epilogue; - rc = syscall(SC_get_environment, &environ); - if (rc < 0) - goto epilogue; - status = main(argc, argv); + int status = main(argc, argv); fflush(stdout); fflush(stderr); -epilogue: syscall(SC_exit, status); // Birger's birthday <3 diff --git a/Userland/.gitignore b/Userland/.gitignore index 53b51e01f4..ccbf5ecba9 100644 --- a/Userland/.gitignore +++ b/Userland/.gitignore @@ -34,3 +34,4 @@ pape ln df su +env diff --git a/Userland/Makefile b/Userland/Makefile index 76a1f97720..ee357c30d7 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -30,6 +30,7 @@ OBJS = \ df.o \ ln.o \ su.o \ + env.o \ rm.o APPS = \ @@ -65,6 +66,7 @@ APPS = \ ln \ df \ su \ + env \ rm ARCH_FLAGS = @@ -184,6 +186,9 @@ df: df.o su: su.o $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a +env: env.o + $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a + .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Userland/env.cpp b/Userland/env.cpp new file mode 100644 index 0000000000..0a2a0e39d5 --- /dev/null +++ b/Userland/env.cpp @@ -0,0 +1,9 @@ +#include +#include + +int main(int, char**) +{ + for (size_t i = 0; environ[i]; ++i) + printf("%s\n", environ[i]); + return 0; +}