From ff7fc6511aed8b7c70a49e65d429bdd7e751cd8d Mon Sep 17 00:00:00 2001 From: Aaron <10217842+byteduck@users.noreply.github.com> Date: Sat, 2 Dec 2023 23:39:17 -0800 Subject: [PATCH] Fix pointer casting tomfoolery preventing boot on release kernel --- .gitignore | 4 ++- CMakeLists.txt | 3 +- kernel/kstd/cstring.cpp | 10 +++++- kernel/memory/Stack.h | 56 +++++-------------------------- kernel/tasking/ProcessArgs.cpp | 16 ++++----- kernel/tasking/Thread.cpp | 60 +++++++++++++++++----------------- 6 files changed, 61 insertions(+), 88 deletions(-) diff --git a/.gitignore b/.gitignore index 85ccf608..2e091162 100644 --- a/.gitignore +++ b/.gitignore @@ -94,4 +94,6 @@ toolchain/build toolchain/sysroot toolchain/edit -user/ \ No newline at end of file +user/ +compile_commands.json +.cache/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 4492b4ed..941fe29a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0) PROJECT(duckOS C CXX ASM) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_SYSROOT ${CMAKE_BINARY_DIR}/root) set(CMAKE_STAGING_PREFIX ${CMAKE_BINARY_DIR}/root) @@ -87,4 +88,4 @@ ADD_CUSTOM_TARGET(qemu ADD_CUSTOM_TARGET(tests COMMAND ${CMAKE_SOURCE_DIR}/scripts/qemu.sh kernel-tests=true USES_TERMINAL -) \ No newline at end of file +) diff --git a/kernel/kstd/cstring.cpp b/kernel/kstd/cstring.cpp index 5509dcec..c888419b 100644 --- a/kernel/kstd/cstring.cpp +++ b/kernel/kstd/cstring.cpp @@ -57,7 +57,15 @@ extern "C" void *memcpy(void *dest, const void *src, size_t count){ } extern "C" void* memmove(void* dest, const void* src, size_t n) { - return __builtin_memmove(dest, src, n); + if (dest < src) + return memcpy(dest, src, n); + + uint8_t* dest8 = (uint8_t*) dest; + const uint8_t* src8 = (const uint8_t*) src; + for (dest8 += n, src8 += n; n--;) + *--dest8 = *--src8; + + return dest; } void* memcpy_uint32(uint32_t* d, uint32_t* s, size_t n) { diff --git a/kernel/memory/Stack.h b/kernel/memory/Stack.h index 7674fb87..e4699283 100644 --- a/kernel/memory/Stack.h +++ b/kernel/memory/Stack.h @@ -24,64 +24,31 @@ class Stack { public: Stack(void* stackptr, size_t real_stackptr): - _stackptr(stackptr), - _stackptr8(reinterpret_cast(_stackptr)), - _stackptr16(reinterpret_cast(_stackptr)), - _stackptr32(reinterpret_cast(_stackptr)), - _stackptrsizet(reinterpret_cast(_stackptr)), - _stackptrint(reinterpret_cast(_stackptr)), + _stackptr((size_t) stackptr), _real_stackptr(real_stackptr) {} Stack(void* stackptr): Stack(stackptr, (size_t) stackptr) {} Stack(const Stack& other): _stackptr(other._stackptr), - _stackptr8(reinterpret_cast(_stackptr)), - _stackptr16(reinterpret_cast(_stackptr)), - _stackptr32(reinterpret_cast(_stackptr)), - _stackptrsizet(reinterpret_cast(_stackptr)), - _stackptrint(reinterpret_cast(_stackptr)), _real_stackptr(other._real_stackptr) {} inline Stack& operator=(const Stack& other) noexcept { _stackptr = other._stackptr; - _stackptr8 = reinterpret_cast(_stackptr); - _stackptr16 = reinterpret_cast(_stackptr); - _stackptr32 = reinterpret_cast(_stackptr); - _stackptrsizet = reinterpret_cast(_stackptr); - _stackptrint = reinterpret_cast(_stackptr); _real_stackptr = other._real_stackptr; return *this; } - inline void push8(uint8_t val) { - *--_stackptr8 = val; - _real_stackptr -= sizeof(uint8_t); - } - - inline void push16(uint16_t val) { - *--_stackptr16 = val; - _real_stackptr -= sizeof(uint16_t); - } - - inline void push32(uint32_t val) { - *--_stackptr32 = val; - _real_stackptr -= sizeof(uint32_t); - } - - inline void push_sizet(size_t val) { - *--_stackptrsizet = val; - _real_stackptr -= sizeof(size_t); - } - - inline void push_int(int val) { - *--_stackptrint = val; - _real_stackptr -= sizeof(int); + template + inline void push(T val) { + _stackptr -= sizeof(val); + _real_stackptr -= sizeof(T); + *((T*) _stackptr) = val; } inline void push_string(const char* str) { size_t len = strlen(str) + 1; - _stackptr8 -= len; + _stackptr -= len; _real_stackptr -= sizeof(char) * len; strcpy((char*)_stackptr, str); } @@ -91,16 +58,11 @@ class Stack { } inline void* stackptr() const { - return _stackptr; + return (void*) _stackptr; } private: size_t _real_stackptr; - void* _stackptr; - uint8_t*& _stackptr8; - uint16_t*& _stackptr16; - uint32_t*& _stackptr32; - size_t*& _stackptrsizet; - int*& _stackptrint; + size_t _stackptr; }; diff --git a/kernel/tasking/ProcessArgs.cpp b/kernel/tasking/ProcessArgs.cpp index 9811b600..864cf298 100644 --- a/kernel/tasking/ProcessArgs.cpp +++ b/kernel/tasking/ProcessArgs.cpp @@ -41,20 +41,20 @@ void ProcessArgs::setup_stack(Stack& stack) { } //Copy pointers to all args into stack - stack.push32(0); + stack.push(0); for(auto i = argv.size(); i > 0; i--) - stack.push32(argp[i - 1]); + stack.push(argp[i - 1]); size_t argvp = stack.real_stackptr(); //Copy pointers to all env into stack - stack.push32(0); + stack.push(0); for(auto i = env.size(); i > 0; i--) - stack.push32(envp[i - 1]); + stack.push(envp[i - 1]); size_t envpp = stack.real_stackptr(); //Push argc, argv, and env on to stack - stack.push_sizet(envpp); //env - stack.push_sizet(argvp); //argv - stack.push_int(argv.size()); //argc - stack.push32(0); + stack.push(envpp); //env + stack.push(argvp); //argv + stack.push(argv.size()); //argc + stack.push(0); } diff --git a/kernel/tasking/Thread.cpp b/kernel/tasking/Thread.cpp index f27c9d4d..873622cc 100644 --- a/kernel/tasking/Thread.cpp +++ b/kernel/tasking/Thread.cpp @@ -158,9 +158,9 @@ Thread::Thread(Process* process, tid_t tid, void* (*entry_func)(void* (*)(void*) } //Set up the user stack for the thread arguments - user_stack.push_sizet((size_t) arg); - user_stack.push_sizet((size_t) thread_func); - user_stack.push_sizet(0); + user_stack.push((size_t) arg); + user_stack.push((size_t) thread_func); + user_stack.push(0); //Setup the kernel stack with register states if(is_kernel_mode()) @@ -435,8 +435,8 @@ bool Thread::call_signal_handler(int signal) { _signal_stack_top = _sighandler_kstack_region->end(); //Push signal number and fake return address to the stack - user_stack.push_int(signal); - user_stack.push_sizet(SIGNAL_RETURN_FAKE_ADDR); + user_stack.push(signal); + user_stack.push(SIGNAL_RETURN_FAKE_ADDR); //Setup signal registers signal_registers.eflags = 0x202; @@ -539,35 +539,35 @@ Thread* Thread::next_thread() { void Thread::setup_kernel_stack(Stack& kernel_stack, size_t user_stack_ptr, Registers& regs) { //If usermode, push ss and useresp - if(!is_kernel_mode()) { - kernel_stack.push32(0x23); - kernel_stack.push_sizet(user_stack_ptr); + if(__builtin_expect(!is_kernel_mode(), true)) { + kernel_stack.push(0x23); + kernel_stack.push(user_stack_ptr); } //Push EFLAGS, CS, and EIP for iret - kernel_stack.push32(regs.eflags); // eflags - kernel_stack.push32(regs.cs); // cs - kernel_stack.push32(regs.eip); // eip - - kernel_stack.push32(regs.eax); - kernel_stack.push32(regs.ebx); - kernel_stack.push32(regs.ecx); - kernel_stack.push32(regs.edx); - kernel_stack.push32(regs.ebp); - kernel_stack.push32(regs.edi); - kernel_stack.push32(regs.esi); - kernel_stack.push32(regs.ds); - kernel_stack.push32(regs.es); - kernel_stack.push32(regs.fs); - kernel_stack.push32(regs.gs); + kernel_stack.push(regs.eflags); // eflags + kernel_stack.push(regs.cs); // cs + kernel_stack.push(regs.eip); // eip + + kernel_stack.push(regs.eax); + kernel_stack.push(regs.ebx); + kernel_stack.push(regs.ecx); + kernel_stack.push(regs.edx); + kernel_stack.push(regs.ebp); + kernel_stack.push(regs.edi); + kernel_stack.push(regs.esi); + kernel_stack.push(regs.ds); + kernel_stack.push(regs.es); + kernel_stack.push(regs.fs); + kernel_stack.push(regs.gs); if(_process->pid() != 0 || _tid != 0) { - kernel_stack.push_sizet((size_t) TaskManager::proc_first_preempt); - kernel_stack.push32(0x2u); /* Kernel eflags: We don't want interrupts enabled */ - kernel_stack.push32(regs.ebx); /* Kernel ebx */ - kernel_stack.push32(regs.esi); /* Kernel esi */ - kernel_stack.push32(regs.edi); /* Kernel edi */ - kernel_stack.push32(0); //Fake popped EBP + kernel_stack.push((size_t) TaskManager::proc_first_preempt); + kernel_stack.push(0x2u); /* Kernel eflags: We don't want interrupts enabled */ + kernel_stack.push(regs.ebx); /* Kernel ebx */ + kernel_stack.push(regs.esi); /* Kernel esi */ + kernel_stack.push(regs.edi); /* Kernel edi */ + kernel_stack.push(0); //Fake popped EBP } regs.esp = (size_t) kernel_stack.stackptr(); @@ -698,4 +698,4 @@ void Thread::die_from_signal(int signal) { // If the signal has no handler and is KILL or FATAL, then kill all threads // Get the current thread as a raw pointer, so that if the current thread is part of this process the reference doesn't stay around _process->die(); -} \ No newline at end of file +}