From 59fe56302f47f3284480ef83aa7b3c180be59297 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 15 Dec 2022 03:08:16 +0200 Subject: [PATCH] Thread arguments are now available from it's stack --- Execute/Spawn.cpp | 16 +-- KThread.cpp | 3 +- SystemCalls/Native.cpp | 2 +- Tasking/Task.cpp | 251 +++++++++++++++++++---------------------- 4 files changed, 126 insertions(+), 146 deletions(-) diff --git a/Execute/Spawn.cpp b/Execute/Spawn.cpp index be9b96e..befdf53 100644 --- a/Execute/Spawn.cpp +++ b/Execute/Spawn.cpp @@ -225,6 +225,7 @@ namespace Execute case DT_PLTRELSZ: { fixme("DT_PLTRELSZ - Size: %ld", Dynamic[i].d_un.d_val); + break; } case DT_PLTGOT: { @@ -419,14 +420,15 @@ namespace Execute Vector auxv; - auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}}); - auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}}); - auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}}); - auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); - auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage}}}); - auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)ELFHeader->e_entry + (uint64_t)ProgramHeader->p_offset}}}); - auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t) "x86_64"}}}); + auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)Path}}}); + auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t) "x86_64"}}}); + auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)ELFHeader->e_entry + (uint64_t)ProgramHeader->p_offset}}}); + auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage}}}); + auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); + auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}}); + auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}}); + auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}}); TCB *Thread = TaskManager->CreateThread(Process, (IP)ELFHeader->e_entry, diff --git a/KThread.cpp b/KThread.cpp index 658bddf..801609c 100644 --- a/KThread.cpp +++ b/KThread.cpp @@ -50,7 +50,8 @@ void KernelMainThread() "TZ=UTC", nullptr}; - const char *argv[3] = { + const char *argv[4] = { + Config.InitPath, "--init", "--critical", nullptr}; diff --git a/SystemCalls/Native.cpp b/SystemCalls/Native.cpp index 4f73b3d..f1c8a5d 100644 --- a/SystemCalls/Native.cpp +++ b/SystemCalls/Native.cpp @@ -53,7 +53,7 @@ static void *NativeSyscallsTable[] = { uint64_t HandleNativeSyscalls(SyscallsFrame *Frame) { #if defined(__amd64__) - debug("rax: %#llx, rbx: %#llx, rcx: %#llx, rdx: %#llx, rsi: %#llx, rdi: %#llx, rbp: %#llx, r8: %#llx, r9: %#llx, r10: %#llx, r11: %#llx, r12: %#llx, r13: %#llx, r14: %#llx, r15: %#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx, Frame->rsi, Frame->rdi, Frame->rbp, Frame->r8, Frame->r9, Frame->r10, Frame->r11, Frame->r12, Frame->r13, Frame->r14, Frame->r15); + // debug("rax: %#llx, rbx: %#llx, rcx: %#llx, rdx: %#llx, rsi: %#llx, rdi: %#llx, rbp: %#llx, r8: %#llx, r9: %#llx, r10: %#llx, r11: %#llx, r12: %#llx, r13: %#llx, r14: %#llx, r15: %#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx, Frame->rsi, Frame->rdi, Frame->rbp, Frame->r8, Frame->r9, Frame->r10, Frame->r11, Frame->r12, Frame->r13, Frame->r14, Frame->r15); if (Frame->rax > sizeof(NativeSyscallsTable)) { fixme("Syscall %lld not implemented", Frame->rax); diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index 05abb26..e142d40 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -777,148 +777,125 @@ namespace Tasking Thread->Registers.rflags.ID = 1; Thread->Registers.rsp = ((uint64_t)Thread->Stack->GetStackTop()); - if (Compatibility == TaskCompatibility::Linux) // Not tested and probably not working + uint64_t ArgvSize = 0; + if (argv) + while (argv[ArgvSize] != nullptr) + ArgvSize++; + + uint64_t EnvpSize = 0; + if (envp) + while (envp[EnvpSize] != nullptr) + EnvpSize++; + + debug("ArgvSize: %d", ArgvSize); + debug("EnvpSize: %d", EnvpSize); + + /* https://articles.manugarg.com/aboutelfauxiliaryvectors.html */ + /* https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9 */ + // rsp is the top of the stack + char *Stack = (char *)Thread->Stack->GetStackPhysicalTop(); + // Temporary stack pointer for strings + char *StackStrings = (char *)Stack; + char *StackStringsVirtual = (char *)Thread->Stack->GetStackTop(); + + // Store string pointers for later + uint64_t ArgvStrings[ArgvSize]; + uint64_t EnvpStrings[EnvpSize]; + + for (uint64_t i = 0; i < ArgvSize; i++) { - // https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9 - // What is a "eightbyte"? unsigned long? 1 eightbyte = 8 bytes? 2 eightbyte each = 16 bytes? - uint64_t TmpStack = Thread->Registers.rsp; - uint64_t TmpStack2 = TmpStack; - uint64_t *TmpStackPtr = (uint64_t *)TmpStack; - - // TODO: argc, argv, envp, auxv not tested and probably not working - // foreach (auto var in envp) - // { - // TmpStack -= strlen(var) + 1; - // strcpy((char *)TmpStack, var); - // } - - // foreach (auto var in argv) - // { - // TmpStack -= strlen(var) + 1; - // strcpy((char *)TmpStack, var); - // } - - /* align by 16 */ - TmpStack = (uint64_t)((uint64_t)TmpStack - ((uint64_t)TmpStack & 0x0F)); - - /* TODO: more alignment here? */ - - /* auxv null */ - TmpStack -= sizeof(uint64_t); - POKE(uint64_t, TmpStack) = (uint64_t)0; - /* This should be included too? */ - TmpStack -= sizeof(uint64_t); - POKE(uint64_t, TmpStack) = (uint64_t)0; - - /* auxv */ - foreach (auto var in auxv) - { - if (var.archaux.a_type == AT_ENTRY) - Thread->Registers.rdi = var.archaux.a_un.a_val; - - TmpStack -= sizeof(uint64_t) * 2; - POKE(uint64_t, TmpStack) = (uint64_t)var.archaux.a_type; - TmpStack -= sizeof(uint64_t) * 2; - POKE(uint64_t, TmpStack) = (uint64_t)var.archaux.a_un.a_val; - } - - /* empty */ - TmpStack -= sizeof(uint64_t); - POKE(uint64_t, TmpStack) = 0; - - /* envp pointers */ - // for (uint64_t i = 0; i < envp.size(); i++) - // { - // /* Not sure if this works */ - // TmpStack2 -= strlen(envp[i]) + 1; - // TmpStackPtr[i] = TmpStack2; - // } - - /* empty */ - TmpStack -= sizeof(uint64_t); - POKE(uint64_t, TmpStack) = 0; - - /* argv pointers */ - // for (uint64_t i = 0; i < argv.size(); i++) - // { - // /* Not sure if this works */ - // TmpStack2 -= strlen(argv[i]) + 1; - // TmpStackPtr[i] = TmpStack2; - // } - - /* argc */ - TmpStack -= sizeof(uint64_t); - // POKE(uint64_t, TmpStack) = argv.size() - 1; - - Thread->Registers.rsp -= (uint64_t)Thread->Stack->GetStackTop() - TmpStack; + // Subtract the length of the string and the null terminator + StackStrings -= strlen(argv[i]) + 1; + StackStringsVirtual -= strlen(argv[i]) + 1; + // Store the pointer to the string + ArgvStrings[i] = (uint64_t)StackStringsVirtual; + // Copy the string to the stack + strcpy(StackStrings, argv[i]); } - else // Native + + for (uint64_t i = 0; i < EnvpSize; i++) { - uint64_t ArgvSize = 0; - if (argv) - while (argv[ArgvSize] != nullptr) - ArgvSize++; - - uint64_t EnvpSize = 0; - if (envp) - while (envp[EnvpSize] != nullptr) - EnvpSize++; - - debug("ArgvSize: %d", ArgvSize); - debug("EnvpSize: %d", EnvpSize); - - Memory::Virtual ArgMap = Memory::Virtual(Parent->PageTable); - - char **_argv = (char **)KernelAllocator.RequestPages(TO_PAGES(ArgvSize * sizeof(char *))); - char **_envp = (char **)KernelAllocator.RequestPages(TO_PAGES(EnvpSize * sizeof(char *))); - - debug("Argv: %#lx", _argv); - debug("Envp: %#lx", _envp); - - for (uint64_t i = 0; i < TO_PAGES(ArgvSize * sizeof(char *)); i++) - ArgMap.Map((void *)((uint64_t)_argv + (i * PAGE_SIZE)), - (void *)((uint64_t)_argv + (i * PAGE_SIZE)), - Memory::PTFlag::RW | Memory::PTFlag::US); - - for (uint64_t i = 0; i < TO_PAGES(EnvpSize * sizeof(char *)); i++) - ArgMap.Map((void *)((uint64_t)_envp + (i * PAGE_SIZE)), - (void *)((uint64_t)_envp + (i * PAGE_SIZE)), - Memory::PTFlag::RW | Memory::PTFlag::US); - - for (uint64_t i = 0; i < ArgvSize; i++) - { - _argv[i] = (char *)KernelAllocator.RequestPages(TO_PAGES(strlen(argv[i]) + 1)); - strcpy(_argv[i], argv[i]); - for (uint64_t j = 0; j < TO_PAGES(strlen(argv[i]) + 1); j++) - ArgMap.Map((void *)((uint64_t)_argv[i] + (j * PAGE_SIZE)), - (void *)((uint64_t)_argv[i] + (j * PAGE_SIZE)), - Memory::PTFlag::RW | Memory::PTFlag::US); - } - - for (uint64_t i = 0; i < EnvpSize; i++) - { - _envp[i] = (char *)KernelAllocator.RequestPages(TO_PAGES(strlen(envp[i]) + 1)); - strcpy(_envp[i], envp[i]); - for (uint64_t j = 0; j < TO_PAGES(strlen(envp[i]) + 1); j++) - ArgMap.Map((void *)((uint64_t)_envp[i] + (j * PAGE_SIZE)), - (void *)((uint64_t)_envp[i] + (j * PAGE_SIZE)), - Memory::PTFlag::RW | Memory::PTFlag::US); - } - - _argv[ArgvSize] = nullptr; - _envp[EnvpSize] = nullptr; - - Thread->Registers.rdi = (uint64_t)ArgvSize; - Thread->Registers.rsi = (uint64_t)_argv; - Thread->Registers.rdx = (uint64_t)EnvpSize; - Thread->Registers.rcx = (uint64_t)_envp; - - for (uint64_t i = 0; i < ArgvSize; i++) - debug("argv[%d]: %s", i, _argv[i]); - for (uint64_t i = 0; i < EnvpSize; i++) - debug("envp[%d]: %s", i, _envp[i]); + // Subtract the length of the string and the null terminator + StackStrings -= strlen(envp[i]) + 1; + StackStringsVirtual -= strlen(envp[i]) + 1; + // Store the pointer to the string + EnvpStrings[i] = (uint64_t)StackStringsVirtual; + // Copy the string to the stack + strcpy(StackStrings, envp[i]); } + // Align the stack to 16 bytes + StackStrings -= (uint64_t)StackStrings & 0xF; + // Set "Stack" to the new stack pointer + Stack = (char *)StackStrings; + // If argv and envp sizes are odd then we need to align the stack + Stack -= (ArgvSize + EnvpSize) % 2; + + // We need 8 bit pointers for the stack from here + uint64_t *Stack64 = (uint64_t *)Stack; + + // Store the null terminator + Stack64--; + *Stack64 = AT_NULL; + + // Store auxillary vector + foreach (AuxiliaryVector var in auxv) + { + // Subtract the size of the auxillary vector + Stack64 -= sizeof(Elf64_auxv_t) / sizeof(uint64_t); + // Store the auxillary vector + POKE(Elf64_auxv_t, Stack64) = var.archaux; + // TODO: Store strings to the stack + } + + // Store the null terminator + Stack64--; + *Stack64 = AT_NULL; + + // Store EnvpStrings[] to the stack + Stack64 -= EnvpSize; // (1 Stack64 = 8 bits; Stack64 = 8 * EnvpSize) + for (uint64_t i = 0; i < EnvpSize; i++) + { + *(Stack64 + i) = (uint64_t)EnvpStrings[i]; + debug("EnvpStrings[%d]: %#lx", i, EnvpStrings[i]); + } + + // Store the null terminator + Stack64--; + *Stack64 = AT_NULL; + + // Store ArgvStrings[] to the stack + Stack64 -= ArgvSize; // (1 Stack64 = 8 bits; Stack64 = 8 * ArgvSize) + for (uint64_t i = 0; i < ArgvSize; i++) + { + *(Stack64 + i) = (uint64_t)ArgvStrings[i]; + debug("ArgvStrings[%d]: %#lx", i, ArgvStrings[i]); + } + + // Store the argc + Stack64--; + *Stack64 = ArgvSize; + + // Set "Stack" to the new stack pointer + Stack = (char *)Stack64; + + /* We need the virtual address but because we are in the kernel we can't use the process page table. + So we modify the physical address and store how much we need to subtract to get the virtual address for RSP. */ + uint64_t SubtractStack = (uint64_t)Thread->Stack->GetStackPhysicalTop() - (uint64_t)Stack; + debug("SubtractStack: %#lx", SubtractStack); + + // Set the stack pointer to the new stack + Thread->Registers.rsp = ((uint64_t)Thread->Stack->GetStackTop() - SubtractStack); + +#ifdef DEBUG + DumpData("Stack Data", (void *)((uint64_t)Thread->Stack->GetStackPhysicalTop() - (uint64_t)SubtractStack), SubtractStack); +#endif + + Thread->Registers.rdi = (uint64_t)ArgvSize; // argc + Thread->Registers.rsi = (uint64_t)(Thread->Registers.rsp + 8); // argv + Thread->Registers.rcx = (uint64_t)EnvpSize; // envc + Thread->Registers.rdx = (uint64_t)(Thread->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp + /* We need to leave the libc's crt to make a syscall when the Thread is exited or we are going to get GPF or PF exception. */ Memory::Virtual uva = Memory::Virtual(Parent->PageTable);