From 41db47717374df5bd340e2eeb55f8dbd416e3f45 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 10 Jun 2023 13:11:25 +0300 Subject: [PATCH] Update kernel --- .vscode/c_cpp_properties.json | 404 +++---- .vscode/extensions.json | 14 + .vscode/launch.json | 123 +- .../amd64/Bootstrap/Multiboot/2/Multiboot.cpp | 562 ++++----- .../DifferentiatedSystemDescriptionTable.cpp | 2 +- .../amd64/Memory/VirtualMemoryManager.cpp | 149 ++- .../amd64/cpu/InterruptDescriptorTable.cpp | 82 +- Architecture/amd64/rust-target.json | 21 - .../i386/Memory/VirtualMemoryManager.cpp | 77 +- Core/Crash/CrashDetails.cpp | 24 +- Core/Crash/CrashHandler.cpp | 26 +- Core/Crash/Screens/Details.cpp | 45 +- Core/Crash/Screens/Tasks.cpp | 4 +- Core/Crash/UserHandler.cpp | 20 +- Core/Crash/chfcts.hpp | 6 +- Core/Debugger.cpp | 63 +- Core/Driver/Driver.cpp | 2 +- Core/Lock.cpp | 16 +- Core/Memory/Memory.cpp | 20 +- Core/Memory/MemoryManager.cpp | 73 +- Core/Memory/PhysicalMemoryManager.cpp | 14 + Core/PeripheralComponentInterconnect.cpp | 4 +- Core/UndefinedBehaviorSanitization.c | 2 +- Execute/BinaryParse.cpp | 171 +++ Execute/Elf/BaseLoad.cpp | 288 ----- Execute/Elf/ElfBaseLoad.cpp | 187 +++ Execute/Elf/ElfInterpreter.cpp | 155 +++ Execute/Elf/ElfLoader.cpp | 480 ++++++++ Execute/Elf/ElfParse.cpp | 340 ++++++ Execute/Elf/{Rel.cpp => ElfRel.cpp} | 4 +- Execute/Elf/ElfSharedObjects.cpp | 159 +++ Execute/Elf/Exec.cpp | 229 ---- Execute/Elf/Parse.cpp | 330 ------ .../Elf/ParseFunctions/ELFGetDynamicTag.cpp | 62 + Execute/Elf/ParseFunctions/ELFGetSections.cpp | 54 + .../Elf/ParseFunctions/ELFGetSymbolType.cpp | 50 + Execute/Elf/SharedObjects.cpp | 263 ----- Execute/Parse.cpp | 102 -- Execute/Spawn.cpp | 128 +- FileSystem/FS/ustar.cpp | 46 +- FileSystem/Filesystem.cpp | 92 +- Kernel.cpp | 68 +- KernelThread.cpp | 29 +- Library/cxxabi.cpp | 294 ----- Library/libstdc++/class_type_info.cpp | 103 ++ Library/libstdc++/cxxabi.cpp | 221 ++++ .../libstdc++/fundamental_type_info.cpp | 21 +- Library/libstdc++/pbase_type_info.cpp | 88 ++ Library/libstdc++/pointer_type_info.cpp | 42 + Library/libstdc++/si_class_type_info.cpp | 102 ++ .../Dyn.cpp => Library/libstdc++/unwind.cpp | 39 +- Library/{ => std}/errno.cpp | 0 Library/std/typeinfo.cpp | 39 + Makefile | 22 +- Network/NetworkController.cpp | 20 - Recovery/RecoveryMain.cpp | 12 +- SystemCalls/Native.cpp | 823 +++++++------ SystemCalls/Syscalls.cpp | 2 +- Tasking/Scheduler.cpp | 1047 ++++++++--------- Tasking/Task.cpp | 53 +- Tests/Marco.cpp | 4 +- Tests/MemoryAllocation.cpp | 2 +- include/cpu.hpp | 218 ++-- include/debug.h | 30 +- include/elf.h | 998 ++++++++++------ include/emmintrin.h | 23 + include/exec.hpp | 236 ++-- include/filesystem.hpp | 49 +- include/memory.hpp | 59 +- include/msexec.h | 104 +- include/smp.hpp | 4 + include/task.hpp | 67 +- include/types.h | 21 +- include_std/cxxabi.h | 69 ++ include_std/exception | 41 + include_std/std/vector.hpp | 2 +- include_std/stdarg.h | 25 + include_std/stdlib.h | 14 - include_std/typeinfo | 337 ++++++ include_std/unwind.h | 78 ++ kernel.h | 1 + syscalls.h | 121 +- 82 files changed, 6342 insertions(+), 4079 deletions(-) create mode 100644 .vscode/extensions.json delete mode 100644 Architecture/amd64/rust-target.json create mode 100644 Execute/BinaryParse.cpp delete mode 100644 Execute/Elf/BaseLoad.cpp create mode 100644 Execute/Elf/ElfBaseLoad.cpp create mode 100644 Execute/Elf/ElfInterpreter.cpp create mode 100644 Execute/Elf/ElfLoader.cpp create mode 100644 Execute/Elf/ElfParse.cpp rename Execute/Elf/{Rel.cpp => ElfRel.cpp} (98%) create mode 100644 Execute/Elf/ElfSharedObjects.cpp delete mode 100644 Execute/Elf/Exec.cpp delete mode 100644 Execute/Elf/Parse.cpp create mode 100644 Execute/Elf/ParseFunctions/ELFGetDynamicTag.cpp create mode 100644 Execute/Elf/ParseFunctions/ELFGetSections.cpp create mode 100644 Execute/Elf/ParseFunctions/ELFGetSymbolType.cpp delete mode 100644 Execute/Elf/SharedObjects.cpp delete mode 100644 Execute/Parse.cpp delete mode 100644 Library/cxxabi.cpp create mode 100644 Library/libstdc++/class_type_info.cpp create mode 100644 Library/libstdc++/cxxabi.cpp rename Execute/Fex/BaseLoad.cpp => Library/libstdc++/fundamental_type_info.cpp (71%) create mode 100644 Library/libstdc++/pbase_type_info.cpp create mode 100644 Library/libstdc++/pointer_type_info.cpp create mode 100644 Library/libstdc++/si_class_type_info.cpp rename Execute/Elf/Dyn.cpp => Library/libstdc++/unwind.cpp (57%) rename Library/{ => std}/errno.cpp (100%) create mode 100644 Library/std/typeinfo.cpp create mode 100644 include/emmintrin.h create mode 100644 include_std/cxxabi.h create mode 100644 include_std/exception create mode 100644 include_std/stdarg.h create mode 100644 include_std/typeinfo create mode 100644 include_std/unwind.h diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index ffff089..b72c80f 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,219 +1,219 @@ { - "configurations": [ - { - "name": "Fennix x64 (Linux, GCC, debug)", - "includePath": [ - "${workspaceFolder}/include", - "${workspaceFolder}/include/**", - "${workspaceFolder}/include_std", - "${workspaceFolder}/include_std/**" - ], - "defines": [ - "__debug_vscode__", - "KERNEL_NAME=\"Fennix\"", - "KERNEL_VERSION=\"1.0\"", - "GIT_COMMIT=\"0000000000000000000000000000000000000000\"", - "GIT_COMMIT_SHORT=\"0000000\"", - "a64", - "a86", - "DEBUG=\"1\"" - ], - "compilerPath": "${workspaceFolder}/../tools/cross/bin/amd64-elf-gcc", - "cStandard": "c17", - "cppStandard": "c++20", - "intelliSenseMode": "gcc-x64", - "configurationProvider": "ms-vscode.makefile-tools", - "compilerArgs": [ - // Compiler flags - "-fno-pic", - "-fno-pie", - "-mno-red-zone", - "-march=core2", - "-pipe", - "-mcmodel=kernel", - "-fno-builtin", + "configurations": [ + { + "name": "Fennix x64 (Linux, GCC, debug)", + "includePath": [ + "${workspaceFolder}/include", + "${workspaceFolder}/include/**", + "${workspaceFolder}/include_std", + "${workspaceFolder}/include_std/**" + ], + "defines": [ + "__debug_vscode__", + "KERNEL_NAME=\"Fennix\"", + "KERNEL_VERSION=\"1.0\"", + "GIT_COMMIT=\"0000000000000000000000000000000000000000\"", + "GIT_COMMIT_SHORT=\"0000000\"", + "a64", + "a86", + "DEBUG=\"1\"" + ], + "compilerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gcc", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "gcc-x64", + "configurationProvider": "ms-vscode.makefile-tools", + "compilerArgs": [ + // Compiler flags + "-fno-pic", + "-fno-pie", + "-mno-red-zone", + "-march=core2", + "-pipe", + "-mcmodel=kernel", + "-fno-builtin", - // Warnings - "-Wall", - "-Wextra", - "-Wfloat-equal", - "-Wpointer-arith", - "-Wcast-align", - "-Wredundant-decls", - "-Winit-self", - "-Wswitch-default", - "-Wstrict-overflow=5", - "-Wconversion", + // Warnings + "-Wall", + "-Wextra", + "-Wfloat-equal", + "-Wpointer-arith", + "-Wcast-align", + "-Wredundant-decls", + "-Winit-self", + "-Wswitch-default", + "-Wstrict-overflow=5", + "-Wconversion", - // C++ flags - "-fno-rtti", - "-fexceptions", + // C++ flags + "-fno-rtti", + "-fno-exceptions", - // Linker flags - "-T${workspaceFolder}/Architecture/amd64/linker.ld", - "-Wl,-static,--no-dynamic-linker,-ztext", - "-nostdlib", - "-nodefaultlibs", - "-nolibc", - "-zmax-page-size=0x1000", - "-shared", + // Linker flags + "-T${workspaceFolder}/Architecture/amd64/linker.ld", + "-Wl,-static,--no-dynamic-linker,-ztext", + "-nostdlib", + "-nodefaultlibs", + "-nolibc", + "-zmax-page-size=0x1000", + "-shared", - // Debug flags - "-ggdb3", - "-O0", - "-fdiagnostics-color=always", - "-fverbose-asm", - "-fstack-usage", - "-fstack-check", - "-fsanitize=undefined", + // Debug flags + "-ggdb3", + "-O0", + "-fdiagnostics-color=always", + "-fverbose-asm", + "-fstack-usage", + "-fstack-check", + "-fsanitize=undefined", - // VSCode flags - "-ffreestanding", - "-nostdinc", - "-nostdinc++" - ] - }, - { - "name": "Fennix x32 (Linux, GCC, debug)", - "includePath": [ - "${workspaceFolder}/include", - "${workspaceFolder}/include/**", - "${workspaceFolder}/include_std", - "${workspaceFolder}/include_std/**" - ], - "defines": [ - "__debug_vscode__", - "KERNEL_NAME=\"Fennix\"", - "KERNEL_VERSION=\"1.0\"", - "GIT_COMMIT=\"0000000000000000000000000000000000000000\"", - "GIT_COMMIT_SHORT=\"0000000\"", - "a32", - "a86", - "DEBUG=\"1\"" - ], - "compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-elf-gcc", - "cStandard": "c17", - "cppStandard": "c++20", - "intelliSenseMode": "gcc-x86", - "configurationProvider": "ms-vscode.makefile-tools", - "compilerArgs": [ - // Compiler flags - "-fno-pic", - "-fno-pie", - "-mno-80387", - "-mno-mmx", - "-mno-3dnow", - "-mno-red-zone", - "-march=pentium", - "-pipe", - "-msoft-float", - "-fno-builtin", + // VSCode flags + "-ffreestanding", + "-nostdinc", + "-nostdinc++" + ] + }, + { + "name": "Fennix x32 (Linux, GCC, debug)", + "includePath": [ + "${workspaceFolder}/include", + "${workspaceFolder}/include/**", + "${workspaceFolder}/include_std", + "${workspaceFolder}/include_std/**" + ], + "defines": [ + "__debug_vscode__", + "KERNEL_NAME=\"Fennix\"", + "KERNEL_VERSION=\"1.0\"", + "GIT_COMMIT=\"0000000000000000000000000000000000000000\"", + "GIT_COMMIT_SHORT=\"0000000\"", + "a32", + "a86", + "DEBUG=\"1\"" + ], + "compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-fennix-gcc", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "gcc-x86", + "configurationProvider": "ms-vscode.makefile-tools", + "compilerArgs": [ + // Compiler flags + "-fno-pic", + "-fno-pie", + "-mno-80387", + "-mno-mmx", + "-mno-3dnow", + "-mno-red-zone", + "-march=pentium", + "-pipe", + "-msoft-float", + "-fno-builtin", - // Warnings - "-Wall", - "-Wextra", - "-Wfloat-equal", - "-Wpointer-arith", - "-Wcast-align", - "-Wredundant-decls", - "-Winit-self", - "-Wswitch-default", - "-Wstrict-overflow=5", - "-Wconversion", + // Warnings + "-Wall", + "-Wextra", + "-Wfloat-equal", + "-Wpointer-arith", + "-Wcast-align", + "-Wredundant-decls", + "-Winit-self", + "-Wswitch-default", + "-Wstrict-overflow=5", + "-Wconversion", - // C++ flags - "-fno-rtti", - "-fexceptions", + // C++ flags + "-fno-rtti", + "-fno-exceptions", - // Linker flags - "-T${workspaceFolder}/Architecture/i386/linker.ld", - "-Wl,-static,--no-dynamic-linker,-ztext", - "-nostdlib", - "-nodefaultlibs", - "-nolibc", - "-zmax-page-size=0x1000", - "-shared", + // Linker flags + "-T${workspaceFolder}/Architecture/i386/linker.ld", + "-Wl,-static,--no-dynamic-linker,-ztext", + "-nostdlib", + "-nodefaultlibs", + "-nolibc", + "-zmax-page-size=0x1000", + "-shared", - // Debug flags - "-ggdb3", - "-O0", - "-fdiagnostics-color=always", - "-fverbose-asm", - "-fstack-usage", - "-fstack-check", - "-fsanitize=undefined", + // Debug flags + "-ggdb3", + "-O0", + "-fdiagnostics-color=always", + "-fverbose-asm", + "-fstack-usage", + "-fstack-check", + "-fsanitize=undefined", - // VSCode flags - "-ffreestanding", - "-nostdinc", - "-nostdinc++" - ] - }, - { - "name": "Fennix Aarch64 (Linux, GCC, debug)", - "includePath": [ - "${workspaceFolder}/include", - "${workspaceFolder}/include/**", - "${workspaceFolder}/include_std", - "${workspaceFolder}/include_std/**" - ], - "defines": [ - "__debug_vscode__", - "KERNEL_NAME=\"Fennix\"", - "KERNEL_VERSION=\"1.0\"", - "GIT_COMMIT=\"0000000000000000000000000000000000000000\"", - "GIT_COMMIT_SHORT=\"0000000\"", - "aa64", - "DEBUG=\"1\"" - ], - "compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-elf-gcc", - "cStandard": "c17", - "cppStandard": "c++20", - "intelliSenseMode": "linux-gcc-arm64", - "configurationProvider": "ms-vscode.makefile-tools", - "compilerArgs": [ - // Compiler flags - "-pipe", - "-fno-builtin", - "-msoft-float", - "-fPIC", - "-Wstack-protector", + // VSCode flags + "-ffreestanding", + "-nostdinc", + "-nostdinc++" + ] + }, + { + "name": "Fennix Aarch64 (Linux, GCC, debug)", + "includePath": [ + "${workspaceFolder}/include", + "${workspaceFolder}/include/**", + "${workspaceFolder}/include_std", + "${workspaceFolder}/include_std/**" + ], + "defines": [ + "__debug_vscode__", + "KERNEL_NAME=\"Fennix\"", + "KERNEL_VERSION=\"1.0\"", + "GIT_COMMIT=\"0000000000000000000000000000000000000000\"", + "GIT_COMMIT_SHORT=\"0000000\"", + "aa64", + "DEBUG=\"1\"" + ], + "compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-fennix-gcc", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "linux-gcc-arm64", + "configurationProvider": "ms-vscode.makefile-tools", + "compilerArgs": [ + // Compiler flags + "-pipe", + "-fno-builtin", + "-msoft-float", + "-fPIC", + "-Wstack-protector", - // Warnings - "-Wall", - "-Wextra", - "-Wfloat-equal", - "-Wpointer-arith", - "-Wcast-align", - "-Wredundant-decls", - "-Winit-self", - "-Wswitch-default", - "-Wstrict-overflow=5", - "-Wconversion", + // Warnings + "-Wall", + "-Wextra", + "-Wfloat-equal", + "-Wpointer-arith", + "-Wcast-align", + "-Wredundant-decls", + "-Winit-self", + "-Wswitch-default", + "-Wstrict-overflow=5", + "-Wconversion", - // C++ flags - "-fno-rtti", - "-fexceptions", + // C++ flags + "-fno-rtti", + "-fno-exceptions", - // Linker flags - "-T${workspaceFolder}/Architecture/aarch64/linker.ld", - "-fPIC", + // Linker flags + "-T${workspaceFolder}/Architecture/aarch64/linker.ld", + "-fPIC", - // Debug flags - "-ggdb3", - "-O0", - "-fdiagnostics-color=always", - "-fverbose-asm", - "-fstack-usage", - "-fstack-check", - "-fsanitize=undefined", + // Debug flags + "-ggdb3", + "-O0", + "-fdiagnostics-color=always", + "-fverbose-asm", + "-fstack-usage", + "-fstack-check", + "-fsanitize=undefined", - // VSCode flags - "-ffreestanding", - "-nostdinc", - "-nostdinc++" - ] - } - ], - "version": 4 + // VSCode flags + "-ffreestanding", + "-nostdinc", + "-nostdinc++" + ] + } + ], + "version": 4 } \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..091659f --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,14 @@ +{ + "recommendations": [ + "jeff-hykin.better-cpp-syntax", + "aaron-bond.better-comments", + "ms-vscode.cpptools", + "maziac.hex-hover-converter", + "zixuanwang.linkerscript", + "webfreak.debug", + "ibm.output-colorizer", + "wayou.vscode-todo-highlight", + "gruntfuggly.todo-tree", + "13xforever.language-x86-64-assembly" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index b9f9492..a53bf41 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,40 +1,87 @@ { - "version": "0.2.0", - "configurations": [ - { - "name": "Attach to a running VM instance", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/kernel.fsys", - "cwd": "${workspaceFolder}", - "args": [], - "targetArchitecture": "x64", - "MIMode": "gdb", - "miDebuggerPath": "/usr/bin/gdb", - "miDebuggerArgs": "", - "externalConsole": false, - "additionalSOLibSearchPath": "${workspaceFolder}", - "customLaunchSetupCommands": [ - { - "text": "target remote localhost:1234", - "description": "Connect to QEMU remote debugger" - } - ], - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - }, - { - "text": "set breakpoint pending on", - "description": "Make breakpoint pending on future shared library load." - }, - { - "text": "file ${workspaceFolder}/kernel.fsys", - "description": "Load binary." - }, - ] - } - ] + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to a running VM instance", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/kernel.fsys", + "cwd": "${workspaceFolder}", + "args": [], + "targetArchitecture": "x64", + "MIMode": "gdb", + "miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gdb", + "miDebuggerArgs": "", + "externalConsole": false, + "additionalSOLibSearchPath": "${workspaceFolder}", + "customLaunchSetupCommands": [ + { + "text": "target remote localhost:1234", + "description": "Connect to QEMU remote debugger" + } + ], + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "set breakpoint pending on", + "description": "Make breakpoint pending on future shared library load." + }, + { + "text": "file ${workspaceFolder}/kernel.fsys", + "description": "Load binary." + } + ] + }, + { + "name": "Attach to VM w/userspace binaries", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/kernel.fsys", + "cwd": "${workspaceFolder}", + "args": [], + "targetArchitecture": "x64", + "MIMode": "gdb", + "miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gdb", + "miDebuggerArgs": "", + "externalConsole": false, + "additionalSOLibSearchPath": "${workspaceFolder}", + "customLaunchSetupCommands": [ + { + "text": "target remote localhost:1234", + "description": "Connect to QEMU remote debugger" + } + ], + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "set breakpoint pending on", + "description": "Make breakpoint pending on future shared library load." + }, + { + "text": "file ${workspaceFolder}/kernel.fsys", + "description": "Load binary." + }, + { + "text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/bin/init", + "description": "Load /bin/init." + }, + { + "text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/lib/ld.so", + "description": "Load /lib/ld.so." + }, + { + "text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/usr/bin/doom", + "description": "Load /usr/bin/doom." + }, + ], + } + ] } \ No newline at end of file diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp index 74b3729..5ac8531 100644 --- a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp +++ b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp @@ -25,291 +25,291 @@ EXTERNC void multiboot_main(uintptr_t Magic, uintptr_t Info) { - if (Info == NULL || Magic == NULL) - { - if (Magic == NULL) - error("Multiboot magic is NULL"); - if (Info == NULL) - error("Multiboot info is NULL"); - CPU::Stop(); - } - else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC) - { - error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC); - CPU::Stop(); - } + if (Info == NULL || Magic == NULL) + { + if (Magic == NULL) + error("Multiboot magic is NULL"); + if (Info == NULL) + error("Multiboot info is NULL"); + CPU::Stop(); + } + else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC) + { + error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC); + CPU::Stop(); + } - BootInfo mb2binfo{}; + BootInfo mb2binfo{}; - { - uint64_t div = 1193180 / 1000; - outb(0x43, 0xB6); - outb(0x42, (uint8_t)div); - outb(0x42, (uint8_t)(div >> 8)); - uint8_t tmp = inb(0x61); - if (tmp != (tmp | 3)) - outb(0x61, tmp | 3); + { + uint64_t div = 1193180 / 1000; + outb(0x43, 0xB6); + outb(0x42, (uint8_t)div); + outb(0x42, (uint8_t)(div >> 8)); + uint8_t tmp = inb(0x61); + if (tmp != (tmp | 3)) + outb(0x61, tmp | 3); - int pos = 0; - auto InfoAddress = Info; - for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8); - ; - Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7))) - { - if (Tag->type == MULTIBOOT_TAG_TYPE_END) - { - debug("End of multiboot2 tags"); - break; - } + int pos = 0; + auto InfoAddress = Info; + for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8); + ; + Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7))) + { + if (Tag->type == MULTIBOOT_TAG_TYPE_END) + { + debug("End of multiboot2 tags"); + break; + } - switch (Tag->type) - { - case MULTIBOOT_TAG_TYPE_CMDLINE: - { - strncpy(mb2binfo.Kernel.CommandLine, - ((multiboot_tag_string *)Tag)->string, - strlen(((multiboot_tag_string *)Tag)->string)); - debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine); - break; - } - case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: - { - strncpy(mb2binfo.Bootloader.Name, - ((multiboot_tag_string *)Tag)->string, - strlen(((multiboot_tag_string *)Tag)->string)); - debug("Bootloader name: %s", mb2binfo.Bootloader.Name); - break; - } - case MULTIBOOT_TAG_TYPE_MODULE: - { - multiboot_tag_module *module = (multiboot_tag_module *)Tag; - static int module_count = 0; - mb2binfo.Modules[module_count].Address = (void *)(uint64_t)module->mod_start; - mb2binfo.Modules[module_count].Size = module->mod_end - module->mod_start; - strncpy(mb2binfo.Modules[module_count].Path, "(null)", 6); - strncpy(mb2binfo.Modules[module_count].CommandLine, module->cmdline, - strlen(module->cmdline)); - debug("Module: %s", mb2binfo.Modules[module_count].Path); - module_count++; - break; - } - case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: - { - multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag; - fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]", - meminfo->mem_lower, meminfo->mem_upper); - break; - } - case MULTIBOOT_TAG_TYPE_BOOTDEV: - { - multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag; - fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]", - bootdev->biosdev, bootdev->slice, bootdev->part); - break; - } - case MULTIBOOT_TAG_TYPE_MMAP: - { - multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag; - size_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry); - mb2binfo.Memory.Entries = EntryCount; - for (uint32_t i = 0; i < EntryCount; i++) - { - if (i > MAX_MEMORY_ENTRIES) - { - warn("Too many memory entries, skipping the rest..."); - break; - } - multiboot_mmap_entry entry = mmap->entries[i]; - mb2binfo.Memory.Size += entry.len; - switch (entry.type) - { - case MULTIBOOT_MEMORY_AVAILABLE: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = Usable; - break; - case MULTIBOOT_MEMORY_RESERVED: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = Reserved; - break; - case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = ACPIReclaimable; - break; - case MULTIBOOT_MEMORY_NVS: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = ACPINVS; - break; - case MULTIBOOT_MEMORY_BADRAM: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = BadMemory; - break; - default: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = Unknown; - break; - } - debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]", - mb2binfo.Memory.Entry[i].BaseAddress, - mb2binfo.Memory.Entry[i].Length, - mb2binfo.Memory.Entry[i].Type); - } - break; - } - case MULTIBOOT_TAG_TYPE_VBE: - { - multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag; - fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]", - vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len); - break; - } - case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: - { - multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag; - static int fb_count = 0; - mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr; - mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width; - mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height; - mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch; - mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp; - switch (fb->common.framebuffer_type) - { - case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: - { - mb2binfo.Framebuffer[fb_count].Type = Indexed; - break; - } - case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: - { - mb2binfo.Framebuffer[fb_count].Type = RGB; - mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size; - mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position; - mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size; - mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position; - mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size; - mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position; - break; - } - case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: - { - mb2binfo.Framebuffer[fb_count].Type = EGA; - break; - } - default: - { - mb2binfo.Framebuffer[fb_count].Type = Unknown_Framebuffer_Type; - break; - } - } - debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); - debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", - fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type, - fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size, - fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position); - fb_count++; - break; - } - case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: - { - multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag; - mb2binfo.Kernel.Symbols.Num = elf->num; - mb2binfo.Kernel.Symbols.EntSize = elf->entsize; - mb2binfo.Kernel.Symbols.Shndx = elf->shndx; - mb2binfo.Kernel.Symbols.Sections = (uintptr_t)&elf->sections; - break; - } - case MULTIBOOT_TAG_TYPE_APM: - { - multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag; - fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]", - apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len); - break; - } - case MULTIBOOT_TAG_TYPE_EFI32: - { - multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag; - fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size); - break; - } - case MULTIBOOT_TAG_TYPE_EFI64: - { - multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag; - fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size); - break; - } - case MULTIBOOT_TAG_TYPE_SMBIOS: - { - multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag; - fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor); - break; - } - case MULTIBOOT_TAG_TYPE_ACPI_OLD: - { - mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp; - debug("OLD ACPI RSDP: %p", mb2binfo.RSDP); - break; - } - case MULTIBOOT_TAG_TYPE_ACPI_NEW: - { - mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp; - debug("NEW ACPI RSDP: %p", mb2binfo.RSDP); - break; - } - case MULTIBOOT_TAG_TYPE_NETWORK: - { - multiboot_tag_network *net = (multiboot_tag_network *)Tag; - fixme("network->[dhcpack: %p]", net->dhcpack); - break; - } - case MULTIBOOT_TAG_TYPE_EFI_MMAP: - { - multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag; - fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]", - efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap); - break; - } - case MULTIBOOT_TAG_TYPE_EFI_BS: - { - fixme("efi_bs->[%p] (unknown structure)", Tag); - break; - } - case MULTIBOOT_TAG_TYPE_EFI32_IH: - { - multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag; - fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer); - break; - } - case MULTIBOOT_TAG_TYPE_EFI64_IH: - { - multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag; - fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer); - break; - } - case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: - { - multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag; - mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr; - mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000); - mb2binfo.Kernel.Size = ((uint64_t)&_kernel_end - (uint64_t)&_kernel_start) + ((uint64_t)&_bootstrap_end - (uint64_t)&_bootstrap_start); - debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase); - break; - } - default: - { - error("Unknown multiboot2 tag type: %d", Tag->type); - break; - } - } - } + switch (Tag->type) + { + case MULTIBOOT_TAG_TYPE_CMDLINE: + { + strncpy(mb2binfo.Kernel.CommandLine, + ((multiboot_tag_string *)Tag)->string, + strlen(((multiboot_tag_string *)Tag)->string)); + debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine); + break; + } + case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: + { + strncpy(mb2binfo.Bootloader.Name, + ((multiboot_tag_string *)Tag)->string, + strlen(((multiboot_tag_string *)Tag)->string)); + debug("Bootloader name: %s", mb2binfo.Bootloader.Name); + break; + } + case MULTIBOOT_TAG_TYPE_MODULE: + { + multiboot_tag_module *module = (multiboot_tag_module *)Tag; + static int module_count = 0; + mb2binfo.Modules[module_count].Address = (void *)(uint64_t)module->mod_start; + mb2binfo.Modules[module_count].Size = module->mod_end - module->mod_start; + strncpy(mb2binfo.Modules[module_count].Path, "(null)", 6); + strncpy(mb2binfo.Modules[module_count].CommandLine, module->cmdline, + strlen(module->cmdline)); + debug("Module: %s", mb2binfo.Modules[module_count].Path); + module_count++; + break; + } + case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: + { + multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag; + fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]", + meminfo->mem_lower, meminfo->mem_upper); + break; + } + case MULTIBOOT_TAG_TYPE_BOOTDEV: + { + multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag; + fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]", + bootdev->biosdev, bootdev->slice, bootdev->part); + break; + } + case MULTIBOOT_TAG_TYPE_MMAP: + { + multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag; + size_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry); + mb2binfo.Memory.Entries = EntryCount; + for (uint32_t i = 0; i < EntryCount; i++) + { + if (i > MAX_MEMORY_ENTRIES) + { + warn("Too many memory entries, skipping the rest..."); + break; + } + multiboot_mmap_entry entry = mmap->entries[i]; + mb2binfo.Memory.Size += entry.len; + switch (entry.type) + { + case MULTIBOOT_MEMORY_AVAILABLE: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Usable; + break; + case MULTIBOOT_MEMORY_RESERVED: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Reserved; + break; + case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = ACPIReclaimable; + break; + case MULTIBOOT_MEMORY_NVS: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = ACPINVS; + break; + case MULTIBOOT_MEMORY_BADRAM: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = BadMemory; + break; + default: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Unknown; + break; + } + debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]", + mb2binfo.Memory.Entry[i].BaseAddress, + mb2binfo.Memory.Entry[i].Length, + mb2binfo.Memory.Entry[i].Type); + } + break; + } + case MULTIBOOT_TAG_TYPE_VBE: + { + multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag; + fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]", + vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len); + break; + } + case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: + { + multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag; + static int fb_count = 0; + mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr; + mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width; + mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height; + mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch; + mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp; + switch (fb->common.framebuffer_type) + { + case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: + { + mb2binfo.Framebuffer[fb_count].Type = Indexed; + break; + } + case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: + { + mb2binfo.Framebuffer[fb_count].Type = RGB; + mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size; + mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position; + mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size; + mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position; + mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size; + mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position; + break; + } + case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: + { + mb2binfo.Framebuffer[fb_count].Type = EGA; + break; + } + default: + { + mb2binfo.Framebuffer[fb_count].Type = Unknown_Framebuffer_Type; + break; + } + } + debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); + debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", + fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type, + fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size, + fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position); + fb_count++; + break; + } + case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: + { + multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag; + mb2binfo.Kernel.Symbols.Num = elf->num; + mb2binfo.Kernel.Symbols.EntSize = elf->entsize; + mb2binfo.Kernel.Symbols.Shndx = elf->shndx; + mb2binfo.Kernel.Symbols.Sections = (uintptr_t)&elf->sections; + break; + } + case MULTIBOOT_TAG_TYPE_APM: + { + multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag; + fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]", + apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len); + break; + } + case MULTIBOOT_TAG_TYPE_EFI32: + { + multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag; + fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size); + break; + } + case MULTIBOOT_TAG_TYPE_EFI64: + { + multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag; + fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size); + break; + } + case MULTIBOOT_TAG_TYPE_SMBIOS: + { + multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag; + fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor); + break; + } + case MULTIBOOT_TAG_TYPE_ACPI_OLD: + { + mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp; + debug("OLD ACPI RSDP: %p", mb2binfo.RSDP); + break; + } + case MULTIBOOT_TAG_TYPE_ACPI_NEW: + { + mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp; + debug("NEW ACPI RSDP: %p", mb2binfo.RSDP); + break; + } + case MULTIBOOT_TAG_TYPE_NETWORK: + { + multiboot_tag_network *net = (multiboot_tag_network *)Tag; + fixme("network->[dhcpack: %p]", net->dhcpack); + break; + } + case MULTIBOOT_TAG_TYPE_EFI_MMAP: + { + multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag; + fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]", + efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap); + break; + } + case MULTIBOOT_TAG_TYPE_EFI_BS: + { + fixme("efi_bs->[%p] (unknown structure)", Tag); + break; + } + case MULTIBOOT_TAG_TYPE_EFI32_IH: + { + multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag; + fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer); + break; + } + case MULTIBOOT_TAG_TYPE_EFI64_IH: + { + multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag; + fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer); + break; + } + case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: + { + multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag; + mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr; + mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000); + mb2binfo.Kernel.Size = ((uint64_t)&_kernel_end - (uint64_t)&_kernel_start) + ((uint64_t)&_bootstrap_end - (uint64_t)&_bootstrap_start); + debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase); + break; + } + default: + { + error("Unknown multiboot2 tag type: %d", Tag->type); + break; + } + } + } - tmp = inb(0x61) & 0xFC; - outb(0x61, tmp); - } + tmp = inb(0x61) & 0xFC; + outb(0x61, tmp); + } - Entry(&mb2binfo); + Entry(&mb2binfo); } diff --git a/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp b/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp index 1693431..edfeb7a 100644 --- a/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp +++ b/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp @@ -78,7 +78,7 @@ namespace ACPI } else if (Event & ACPI_POWER_BUTTON) { - if (TaskManager) + if (TaskManager && !TaskManager->IsPanic()) { TaskManager->CreateThread(TaskManager->CreateProcess(nullptr, "Shutdown", diff --git a/Architecture/amd64/Memory/VirtualMemoryManager.cpp b/Architecture/amd64/Memory/VirtualMemoryManager.cpp index 4b757c5..4f1c808 100644 --- a/Architecture/amd64/Memory/VirtualMemoryManager.cpp +++ b/Architecture/amd64/Memory/VirtualMemoryManager.cpp @@ -29,15 +29,15 @@ namespace Memory Address &= 0xFFFFFFFFFFFFF000; PageMapIndexer Index = PageMapIndexer(Address); - PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex]; + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; PageDirectoryPointerTableEntryPtr *PDPTE = nullptr; PageDirectoryEntryPtr *PDE = nullptr; PageTableEntryPtr *PTE = nullptr; - if ((PML4.raw & Flag) > 0) + if ((PML4->raw & Flag) > 0) { - PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); + PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12); if (PDPTE) { if ((PDPTE->Entries[Index.PDPTEIndex].Present)) @@ -74,15 +74,15 @@ namespace Memory Address &= 0xFFFFFFFFFFFFF000; PageMapIndexer Index = PageMapIndexer(Address); - PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex]; + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; PageDirectoryPointerTableEntryPtr *PDPTE = nullptr; PageDirectoryEntryPtr *PDE = nullptr; PageTableEntryPtr *PTE = nullptr; - if (PML4.Present) + if (PML4->Present) { - PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); + PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12); if (PDPTE) { if (PDPTE->Entries[Index.PDPTEIndex].Present) @@ -112,6 +112,135 @@ namespace Memory return nullptr; } + Virtual::MapType Virtual::GetMapType(void *VirtualAddress) + { + // 0x1000 aligned + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; + + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + + PageDirectoryPointerTableEntryPtr *PDPTE = nullptr; + PageDirectoryEntryPtr *PDE = nullptr; + PageTableEntryPtr *PTE = nullptr; + + if (PML4->Present) + { + PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12); + if (PDPTE) + { + if (PDPTE->Entries[Index.PDPTEIndex].Present) + { + if (PDPTE->Entries[Index.PDPTEIndex].PageSize) + return MapType::OneGB; + + PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); + if (PDE) + { + if (PDE->Entries[Index.PDEIndex].Present) + { + if (PDE->Entries[Index.PDEIndex].PageSize) + return MapType::TwoMB; + + PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); + if (PTE) + { + if (PTE->Entries[Index.PTEIndex].Present) + return MapType::FourKB; + } + } + } + } + } + } + return MapType::NoMapType; + } + + PageMapLevel5 *Virtual::GetPML5(void *VirtualAddress, MapType Type) + { + stub; /* TODO */ + return nullptr; + } + + PageMapLevel4 *Virtual::GetPML4(void *VirtualAddress, MapType Type) + { + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; + + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + if (PML4->Present) + return PML4; + return nullptr; + } + + PageDirectoryPointerTableEntry *Virtual::GetPDPTE(void *VirtualAddress, MapType Type) + { + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; + + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + if (!PML4->Present) + return nullptr; + + PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); + PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; + if (PDPTE->Present) + return PDPTE; + return nullptr; + } + + PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type) + { + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; + + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + if (!PML4->Present) + return nullptr; + + PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); + PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; + if (!PDPTE->Present) + return nullptr; + + PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12); + PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; + if (PDE->Present) + return PDE; + return nullptr; + } + + PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type) + { + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; + + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + if (!PML4->Present) + return nullptr; + + PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); + PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; + if (!PDPTE->Present) + return nullptr; + + PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12); + PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; + if (!PDE->Present) + return nullptr; + + PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12); + PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex]; + if (PTE->Present) + return PTE; + return nullptr; + } + void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type) { SmartLock(this->MemoryLock); @@ -234,7 +363,7 @@ namespace Memory PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; if (!PML4->Present) { - error("Page %#lx not present", PML4->GetAddress()); + warn("Page %#lx not present", PML4->GetAddress()); return; } @@ -242,7 +371,7 @@ namespace Memory PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; if (!PDPTE->Present) { - error("Page %#lx not present", PDPTE->GetAddress()); + warn("Page %#lx not present", PDPTE->GetAddress()); return; } @@ -256,7 +385,7 @@ namespace Memory PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; if (!PDE->Present) { - error("Page %#lx not present", PDE->GetAddress()); + warn("Page %#lx not present", PDE->GetAddress()); return; } @@ -270,7 +399,7 @@ namespace Memory PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex]; if (!PTE.Present) { - error("Page %#lx not present", PTE.GetAddress()); + warn("Page %#lx not present", PTE.GetAddress()); return; } diff --git a/Architecture/amd64/cpu/InterruptDescriptorTable.cpp b/Architecture/amd64/cpu/InterruptDescriptorTable.cpp index 3cf6f9c..55434ae 100644 --- a/Architecture/amd64/cpu/InterruptDescriptorTable.cpp +++ b/Architecture/amd64/cpu/InterruptDescriptorTable.cpp @@ -475,50 +475,46 @@ namespace InterruptDescriptorTable outb(0xA1, 0xff); } - /* ISR */ + bool EnableISRs = true; +#ifdef DEBUG + EnableISRs = !DebuggerIsAttached; + if (!EnableISRs) + KPrint("\eFFA500The debugger is attached, disabling all ISRs."); +#endif -#ifdef DEBUG - // if (!DebuggerIsAttached) - if (true) - { -#endif - SetEntry(0x0, InterruptHandler_0x0, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x1, InterruptHandler_0x1, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x2, InterruptHandler_0x2, IST2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x3, InterruptHandler_0x3, IST1, TRAP_32BIT, RING3, (!DebuggerIsAttached), GDT_KERNEL_CODE); /* Do not handle breakpoints if we are debugging the kernel. */ - SetEntry(0x4, InterruptHandler_0x4, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x5, InterruptHandler_0x5, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x6, InterruptHandler_0x6, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x7, InterruptHandler_0x7, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x8, InterruptHandler_0x8, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x9, InterruptHandler_0x9, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0xa, InterruptHandler_0xa, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0xb, InterruptHandler_0xb, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0xc, InterruptHandler_0xc, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0xd, InterruptHandler_0xd, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0xe, InterruptHandler_0xe, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0xf, InterruptHandler_0xf, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x10, InterruptHandler_0x10, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x11, InterruptHandler_0x11, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x12, InterruptHandler_0x12, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x13, InterruptHandler_0x13, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x14, InterruptHandler_0x14, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x15, InterruptHandler_0x15, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x16, InterruptHandler_0x16, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x17, InterruptHandler_0x17, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x18, InterruptHandler_0x18, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x19, InterruptHandler_0x19, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x1a, InterruptHandler_0x1a, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x1b, InterruptHandler_0x1b, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x1c, InterruptHandler_0x1c, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x1d, InterruptHandler_0x1d, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x1e, InterruptHandler_0x1e, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); - SetEntry(0x1f, InterruptHandler_0x1f, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); -#ifdef DEBUG - } - else - KPrint("\eFFA500The debugger is attached, not setting up the ISR."); -#endif + /* ISR */ + SetEntry(0x0, InterruptHandler_0x0, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x1, InterruptHandler_0x1, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x2, InterruptHandler_0x2, IST2, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x3, InterruptHandler_0x3, IST1, TRAP_32BIT, RING3, (!DebuggerIsAttached), GDT_KERNEL_CODE); /* Do not handle breakpoints if we are debugging the kernel. */ + SetEntry(0x4, InterruptHandler_0x4, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x5, InterruptHandler_0x5, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x6, InterruptHandler_0x6, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x7, InterruptHandler_0x7, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x8, InterruptHandler_0x8, IST3, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x9, InterruptHandler_0x9, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0xa, InterruptHandler_0xa, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0xb, InterruptHandler_0xb, IST1, TRAP_32BIT, RING0, (!DebuggerIsAttached), GDT_KERNEL_CODE); + SetEntry(0xc, InterruptHandler_0xc, IST3, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0xd, InterruptHandler_0xd, IST3, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0xe, InterruptHandler_0xe, IST3, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0xf, InterruptHandler_0xf, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x10, InterruptHandler_0x10, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x11, InterruptHandler_0x11, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x12, InterruptHandler_0x12, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x13, InterruptHandler_0x13, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x14, InterruptHandler_0x14, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x15, InterruptHandler_0x15, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x16, InterruptHandler_0x16, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x17, InterruptHandler_0x17, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x18, InterruptHandler_0x18, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x19, InterruptHandler_0x19, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x1a, InterruptHandler_0x1a, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x1b, InterruptHandler_0x1b, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x1c, InterruptHandler_0x1c, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x1d, InterruptHandler_0x1d, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x1e, InterruptHandler_0x1e, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); + SetEntry(0x1f, InterruptHandler_0x1f, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE); /* IRQ */ diff --git a/Architecture/amd64/rust-target.json b/Architecture/amd64/rust-target.json deleted file mode 100644 index f3697f1..0000000 --- a/Architecture/amd64/rust-target.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "llvm-target": "x86_64-unknown-none", - "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", - "cpu": "x86-64", - "arch": "x86_64", - "features": "-mmx,-sse,+soft-float", - "target-endian": "little", - "target-pointer-width": "64", - "target-c-int-width": "32", - "os": "none", - "linker-flavor": "ld", - "pre-link-args": { - "ld": [ - "-m64" - ] - }, - "no-compiler-rt": true, - "disable-redzone": true, - "eliminate-frame-pointer": false, - "morestack": false -} \ No newline at end of file diff --git a/Architecture/i386/Memory/VirtualMemoryManager.cpp b/Architecture/i386/Memory/VirtualMemoryManager.cpp index c33a408..6008767 100644 --- a/Architecture/i386/Memory/VirtualMemoryManager.cpp +++ b/Architecture/i386/Memory/VirtualMemoryManager.cpp @@ -29,15 +29,15 @@ namespace Memory Address &= 0xFFFFF000; PageMapIndexer Index = PageMapIndexer(Address); - PageDirectoryEntry PDE = this->Table->Entries[Index.PDEIndex]; + PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageTableEntryPtr *PTE = nullptr; - if ((PDE.raw & Flag) > 0) + if ((PDE->raw & Flag) > 0) { - if (Type == MapType::FourMB && PDE.PageSize) + if (Type == MapType::FourMB && PDE->PageSize) return true; - PTE = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12); + PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12); if (PTE) { if ((PTE->Entries[Index.PTEIndex].Present)) @@ -54,15 +54,15 @@ namespace Memory Address &= 0xFFFFF000; PageMapIndexer Index = PageMapIndexer(Address); - PageDirectoryEntry PDE = this->Table->Entries[Index.PDEIndex]; + PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageTableEntryPtr *PTE = nullptr; - if (PDE.Present) + if (PDE->Present) { - if (PDE.PageSize) - return (void *)((uintptr_t)PDE.GetAddress() << 12); + if (PDE->PageSize) + return (void *)((uintptr_t)PDE->GetAddress() << 12); - PTE = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12); + PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12); if (PTE) { if (PTE->Entries[Index.PTEIndex].Present) @@ -72,6 +72,61 @@ namespace Memory return nullptr; } + Virtual::MapType Virtual::GetMapType(void *VirtualAddress) + { + // 0x1000 aligned + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; + + PageMapIndexer Index = PageMapIndexer(Address); + + PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; + PageTableEntryPtr *PTE = nullptr; + + if (PDE->Present) + { + if (PDE->PageSize) + return MapType::FourMB; + + PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12); + if (PTE) + { + if (PTE->Entries[Index.PTEIndex].Present) + return MapType::FourKB; + } + } + return MapType::NoMapType; + } + + PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type) + { + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; + + PageMapIndexer Index = PageMapIndexer(Address); + PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; + if (PDE->Present) + return PDE; + return nullptr; + } + + PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type) + { + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; + + PageMapIndexer Index = PageMapIndexer(Address); + PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; + if (!PDE->Present) + return nullptr; + + PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12); + PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex]; + if (PTE->Present) + return PTE; + return nullptr; + } + void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type) { SmartLock(this->MemoryLock); @@ -159,7 +214,7 @@ namespace Memory PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; if (!PDE->Present) { - error("Page %#lx not present", PDE->GetAddress()); + warn("Page %#lx not present", PDE->GetAddress()); return; } @@ -173,7 +228,7 @@ namespace Memory PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex]; if (!PTE.Present) { - error("Page %#lx not present", PTE.GetAddress()); + warn("Page %#lx not present", PTE.GetAddress()); return; } diff --git a/Core/Crash/CrashDetails.cpp b/Core/Crash/CrashDetails.cpp index 0730d51..b66c9a2 100644 --- a/Core/Crash/CrashDetails.cpp +++ b/Core/Crash/CrashDetails.cpp @@ -191,29 +191,29 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame) #endif #if defined(a64) - Memory::Virtual vma = Memory::Virtual(((Memory::PageTable *)CPU::x64::readcr3().raw)); + Memory::Virtual vmm = Memory::Virtual(((Memory::PageTable *)CPU::x64::readcr3().raw)); #elif defined(a32) - Memory::Virtual vma = Memory::Virtual(((Memory::PageTable *)CPU::x32::readcr3().raw)); + Memory::Virtual vmm = Memory::Virtual(((Memory::PageTable *)CPU::x32::readcr3().raw)); #elif defined(aa64) - Memory::Virtual vma = Memory::Virtual(); + Memory::Virtual vmm = Memory::Virtual(); #warning "TODO: aa64" #endif - bool PageAvailable = vma.Check((void *)CheckPageFaultAddress); + bool PageAvailable = vmm.Check((void *)CheckPageFaultAddress); debug("Page available (Check(...)): %s. %s", PageAvailable ? "Yes" : "No", (params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result."); if (PageAvailable) { - bool Present = vma.Check((void *)CheckPageFaultAddress); - bool ReadWrite = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW); - bool User = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US); - bool WriteThrough = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT); - bool CacheDisabled = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD); - bool Accessed = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A); - bool Dirty = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D); - bool Global = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G); + bool Present = vmm.Check((void *)CheckPageFaultAddress); + bool ReadWrite = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW); + bool User = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US); + bool WriteThrough = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT); + bool CacheDisabled = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD); + bool Accessed = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A); + bool Dirty = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D); + bool Global = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G); /* ... */ debug("Page available: %s", Present ? "Yes" : "No"); diff --git a/Core/Crash/CrashHandler.cpp b/Core/Crash/CrashHandler.cpp index 2ede6ef..21dd10c 100644 --- a/Core/Crash/CrashHandler.cpp +++ b/Core/Crash/CrashHandler.cpp @@ -708,12 +708,12 @@ namespace CrashHandler uint64_t TotalMemLength = KernelAllocator.GetTotalMemory(); uint64_t ProgressLength = TotalMemLength; UniversalAsynchronousReceiverTransmitter::UART uart(port); - Memory::Virtual vma; + Memory::Virtual vmm; uint8_t *Address = reinterpret_cast(0x0); int Progress = 0; for (size_t i = 0; i < TotalMemLength; i++) { - if (vma.Check(Address)) + if (vmm.Check(Address)) uart.Write(*Address); else if (cBoolSkip[0] == '0') uart.Write((uint8_t)0); @@ -988,9 +988,9 @@ namespace CrashHandler asmv("movq %%dr3, %0" : "=r"(crashdata.dr3)); asmv("movq %%dr6, %0" - : "=r"(crashdata.dr6)); + : "=r"(crashdata.dr6.raw)); asmv("movq %%dr7, %0" - : "=r"(crashdata.dr7)); + : "=r"(crashdata.dr7.raw)); CPUData *cpudata = GetCurrentCPU(); @@ -1041,7 +1041,7 @@ namespace CrashHandler error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, crashdata.efer.raw); error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", crashdata.cr0.raw, crashdata.cr2.raw, crashdata.cr3.raw, crashdata.cr4.raw, crashdata.cr8.raw); - error("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx", crashdata.dr0, crashdata.dr1, crashdata.dr2, crashdata.dr3, crashdata.dr6, crashdata.dr7.raw); + error("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx", crashdata.dr0, crashdata.dr1, crashdata.dr2, crashdata.dr3, crashdata.dr6.raw, crashdata.dr7.raw); error("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x", crashdata.cr0.PE ? "True " : "False", crashdata.cr0.MP ? "True " : "False", crashdata.cr0.EM ? "True " : "False", crashdata.cr0.TS ? "True " : "False", @@ -1073,12 +1073,16 @@ namespace CrashHandler Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne, Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3); - error("DR7: LDR0:%s GDR0:%s LDR1:%s GDR1:%s LDR2:%s GDR2:%s LDR3:%s GDR3:%s CDR0:%s SDR0:%s CDR1:%s SDR1:%s CDR2:%s SDR2:%s CDR3:%s SDR3:%s R:%#x", - crashdata.dr7.LocalDR0 ? "True " : "False", crashdata.dr7.GlobalDR0 ? "True " : "False", crashdata.dr7.LocalDR1 ? "True " : "False", crashdata.dr7.GlobalDR1 ? "True " : "False", - crashdata.dr7.LocalDR2 ? "True " : "False", crashdata.dr7.GlobalDR2 ? "True " : "False", crashdata.dr7.LocalDR3 ? "True " : "False", crashdata.dr7.GlobalDR3 ? "True " : "False", - crashdata.dr7.ConditionsDR0 ? "True " : "False", crashdata.dr7.SizeDR0 ? "True " : "False", crashdata.dr7.ConditionsDR1 ? "True " : "False", crashdata.dr7.SizeDR1 ? "True " : "False", - crashdata.dr7.ConditionsDR2 ? "True " : "False", crashdata.dr7.SizeDR2 ? "True " : "False", crashdata.dr7.ConditionsDR3 ? "True " : "False", crashdata.dr7.SizeDR3 ? "True " : "False", - crashdata.dr7.Reserved); + error("DR6: B0:%s B1:%s B2:%s B3:%s BD:%s BS:%s BT:%s", + crashdata.dr6.B0 ? "True " : "False", crashdata.dr6.B1 ? "True " : "False", crashdata.dr6.B2 ? "True " : "False", crashdata.dr6.B3 ? "True " : "False", + crashdata.dr6.BD ? "True " : "False", crashdata.dr6.BS ? "True " : "False", crashdata.dr6.BT ? "True " : "False"); + + error("DR7: L0:%s G0:%s L1:%s G1:%s L2:%s G2:%s L3:%s G3:%s LE:%s GE:%s GD:%s R/W0:%s LEN0:%s R/W1:%s LEN1:%s R/W2:%s LEN2:%s R/W3:%s LEN3:%s", + crashdata.dr7.L0 ? "True " : "False", crashdata.dr7.G0 ? "True " : "False", crashdata.dr7.L1 ? "True " : "False", crashdata.dr7.G1 ? "True " : "False", + crashdata.dr7.L2 ? "True " : "False", crashdata.dr7.G2 ? "True " : "False", crashdata.dr7.L3 ? "True " : "False", crashdata.dr7.G3 ? "True " : "False", + crashdata.dr7.LE ? "True " : "False", crashdata.dr7.GE ? "True " : "False", crashdata.dr7.GD ? "True " : "False", crashdata.dr7.RW0 ? "True " : "False", + crashdata.dr7.LEN0 ? "True " : "False", crashdata.dr7.RW1 ? "True " : "False", crashdata.dr7.LEN1 ? "True " : "False", crashdata.dr7.RW2 ? "True " : "False", + crashdata.dr7.LEN2 ? "True " : "False", crashdata.dr7.RW3 ? "True " : "False", crashdata.dr7.LEN3 ? "True " : "False"); error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x", crashdata.efer.SCE ? "True " : "False", crashdata.efer.LME ? "True " : "False", crashdata.efer.LMA ? "True " : "False", crashdata.efer.NXE ? "True " : "False", diff --git a/Core/Crash/Screens/Details.cpp b/Core/Crash/Screens/Details.cpp index 4cae548..464c2bd 100644 --- a/Core/Crash/Screens/Details.cpp +++ b/Core/Crash/Screens/Details.cpp @@ -91,11 +91,10 @@ namespace CrashHandler EHPrint("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx\n", data.cr0.raw, data.cr2.raw, data.cr3.raw, data.cr4.raw, data.cr8.raw); EHPrint("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx\n", data.dr0, data.dr1, data.dr2, data.dr3, data.dr6, data.dr7.raw); - EHPrint("\eFC797BCR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n R0:%#x R1:%#x R2:%#x\n", + EHPrint("\eFC797BCR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n", data.cr0.PE ? "True " : "False", data.cr0.MP ? "True " : "False", data.cr0.EM ? "True " : "False", data.cr0.TS ? "True " : "False", data.cr0.ET ? "True " : "False", data.cr0.NE ? "True " : "False", data.cr0.WP ? "True " : "False", data.cr0.AM ? "True " : "False", - data.cr0.NW ? "True " : "False", data.cr0.CD ? "True " : "False", data.cr0.PG ? "True " : "False", - data.cr0.Reserved0, data.cr0.Reserved1, data.cr0.Reserved2); + data.cr0.NW ? "True " : "False", data.cr0.CD ? "True " : "False", data.cr0.PG ? "True " : "False"); EHPrint("\eFCBD79CR2: PFLA: %#llx\n", data.cr2.PFLA); @@ -103,52 +102,48 @@ namespace CrashHandler EHPrint("\e79FC84CR3: PWT:%s PCD:%s PDBR:%#llx\n", data.cr3.PWT ? "True " : "False", data.cr3.PCD ? "True " : "False", data.cr3.PDBR); - EHPrint("\eBD79FCCR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n R0:%#x R1:%#x R2:%#x\n", + EHPrint("\eBD79FCCR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n", data.cr4.VME ? "True " : "False", data.cr4.PVI ? "True " : "False", data.cr4.TSD ? "True " : "False", data.cr4.DE ? "True " : "False", data.cr4.PSE ? "True " : "False", data.cr4.PAE ? "True " : "False", data.cr4.MCE ? "True " : "False", data.cr4.PGE ? "True " : "False", data.cr4.PCE ? "True " : "False", data.cr4.UMIP ? "True " : "False", data.cr4.OSFXSR ? "True " : "False", data.cr4.OSXMMEXCPT ? "True " : "False", data.cr4.LA57 ? "True " : "False", data.cr4.VMXE ? "True " : "False", data.cr4.SMXE ? "True " : "False", data.cr4.PCIDE ? "True " : "False", - data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False", -#if defined(a64) - data.cr4.Reserved0, data.cr4.Reserved1, data.cr4.Reserved2); -#elif defined(a32) - data.cr4.Reserved0, data.cr4.Reserved1, 0); -#endif + data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False"); EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL); #endif // a64 || a32 #if defined(a64) - EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n", + EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n", data.Frame->rflags.CF ? "True " : "False", data.Frame->rflags.PF ? "True " : "False", data.Frame->rflags.AF ? "True " : "False", data.Frame->rflags.ZF ? "True " : "False", data.Frame->rflags.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False", data.Frame->rflags.OF ? "True " : "False", data.Frame->rflags.IOPL ? "True " : "False", data.Frame->rflags.NT ? "True " : "False", data.Frame->rflags.RF ? "True " : "False", data.Frame->rflags.VM ? "True " : "False", data.Frame->rflags.AC ? "True " : "False", data.Frame->rflags.VIF ? "True " : "False", data.Frame->rflags.VIP ? "True " : "False", - data.Frame->rflags.ID ? "True " : "False", data.Frame->rflags.AlwaysOne, - data.Frame->rflags.Reserved0, data.Frame->rflags.Reserved1, data.Frame->rflags.Reserved2, data.Frame->rflags.Reserved3); + data.Frame->rflags.ID ? "True " : "False", data.Frame->rflags.AlwaysOne); #elif defined(a32) - EHPrint("\eFCFC02EFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x\n", + EHPrint("\eFCFC02EFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n", data.Frame->eflags.CF ? "True " : "False", data.Frame->eflags.PF ? "True " : "False", data.Frame->eflags.AF ? "True " : "False", data.Frame->eflags.ZF ? "True " : "False", data.Frame->eflags.SF ? "True " : "False", data.Frame->eflags.TF ? "True " : "False", data.Frame->eflags.IF ? "True " : "False", data.Frame->eflags.DF ? "True " : "False", data.Frame->eflags.OF ? "True " : "False", data.Frame->eflags.IOPL ? "True " : "False", data.Frame->eflags.NT ? "True " : "False", data.Frame->eflags.RF ? "True " : "False", data.Frame->eflags.VM ? "True " : "False", data.Frame->eflags.AC ? "True " : "False", data.Frame->eflags.VIF ? "True " : "False", data.Frame->eflags.VIP ? "True " : "False", - data.Frame->eflags.ID ? "True " : "False", data.Frame->eflags.AlwaysOne, - data.Frame->eflags.Reserved0, data.Frame->eflags.Reserved1, data.Frame->eflags.Reserved2); + data.Frame->eflags.ID ? "True " : "False", data.Frame->eflags.AlwaysOne); #elif defined(aa64) #endif #if defined(a86) - EHPrint("\eA0F0F0DR7: LDR0:%s GDR0:%s LDR1:%s GDR1:%s\n LDR2:%s GDR2:%s LDR3:%s GDR3:%s\n CDR0:%s SDR0:%s CDR1:%s SDR1:%s\n CDR2:%s SDR2:%s CDR3:%s SDR3:%s\n R:%#x\n", - data.dr7.LocalDR0 ? "True " : "False", data.dr7.GlobalDR0 ? "True " : "False", data.dr7.LocalDR1 ? "True " : "False", data.dr7.GlobalDR1 ? "True " : "False", - data.dr7.LocalDR2 ? "True " : "False", data.dr7.GlobalDR2 ? "True " : "False", data.dr7.LocalDR3 ? "True " : "False", data.dr7.GlobalDR3 ? "True " : "False", - data.dr7.ConditionsDR0 ? "True " : "False", data.dr7.SizeDR0 ? "True " : "False", data.dr7.ConditionsDR1 ? "True " : "False", data.dr7.SizeDR1 ? "True " : "False", - data.dr7.ConditionsDR2 ? "True " : "False", data.dr7.SizeDR2 ? "True " : "False", data.dr7.ConditionsDR3 ? "True " : "False", data.dr7.SizeDR3 ? "True " : "False", - data.dr7.Reserved); + EHPrint("\eA0A0A0DR6: B0:%s B1:%s B2:%s B3:%s BD:%s BS:%s BT:%s\n", + data.dr6.B0 ? "True " : "False", data.dr6.B1 ? "True " : "False", data.dr6.B2 ? "True " : "False", data.dr6.B3 ? "True " : "False", + data.dr6.BD ? "True " : "False", data.dr6.BS ? "True " : "False", data.dr6.BT ? "True " : "False"); + + EHPrint("\eA0F0F0DR7: L0:%s G0:%s L1:%s G1:%s\n L2:%s G2:%s L3:%s G3:%s\n LE:%s GE:%s GD:%s\n R/W0:%s LEN0:%s R/W1:%s LEN1:%s\n R/W2:%s LEN2:%s R/W3:%s LEN3:%s\n", + data.dr7.L0 ? "True " : "False", data.dr7.G0 ? "True " : "False", data.dr7.L1 ? "True " : "False", data.dr7.G1 ? "True " : "False", + data.dr7.L2 ? "True " : "False", data.dr7.G2 ? "True " : "False", data.dr7.L3 ? "True " : "False", data.dr7.G3 ? "True " : "False", + data.dr7.LE ? "True " : "False", data.dr7.GE ? "True " : "False", data.dr7.GD ? "True " : "False", data.dr7.RW0 ? "True " : "False", + data.dr7.LEN0 ? "True " : "False", data.dr7.RW1 ? "True " : "False", data.dr7.LEN1 ? "True " : "False", data.dr7.RW2 ? "True " : "False", + data.dr7.LEN2 ? "True " : "False", data.dr7.RW3 ? "True " : "False", data.dr7.LEN3 ? "True " : "False"); #ifdef a64 - EHPrint("\e009FF0EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n R0:%#x R1:%#x R2:%#x\n", + EHPrint("\e009FF0EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n\n", data.efer.SCE ? "True " : "False", data.efer.LME ? "True " : "False", data.efer.LMA ? "True " : "False", data.efer.NXE ? "True " : "False", - data.efer.SVME ? "True " : "False", data.efer.LMSLE ? "True " : "False", data.efer.FFXSR ? "True " : "False", data.efer.TCE ? "True " : "False", - data.efer.Reserved0, data.efer.Reserved1, data.efer.Reserved2); + data.efer.SVME ? "True " : "False", data.efer.LMSLE ? "True " : "False", data.efer.FFXSR ? "True " : "False", data.efer.TCE ? "True " : "False"); #endif // a64 #endif diff --git a/Core/Crash/Screens/Tasks.cpp b/Core/Crash/Screens/Tasks.cpp index 27be832..97d8c4f 100644 --- a/Core/Crash/Screens/Tasks.cpp +++ b/Core/Crash/Screens/Tasks.cpp @@ -56,10 +56,10 @@ namespace CrashHandler "Terminated", // Terminated }; - std::vector Plist = TaskManager->GetProcessList(); - if (TaskManager) { + std::vector Plist = TaskManager->GetProcessList(); + if (data.Thread) #if defined(a64) EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip); diff --git a/Core/Crash/UserHandler.cpp b/Core/Crash/UserHandler.cpp index 3b7519d..6792b84 100644 --- a/Core/Crash/UserHandler.cpp +++ b/Core/Crash/UserHandler.cpp @@ -250,22 +250,22 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) #ifdef DEBUG if (CurCPU) { - Memory::Virtual vma = Memory::Virtual(CurCPU->CurrentProcess->PageTable); - bool PageAvailable = vma.Check((void *)CheckPageFaultAddress); + Memory::Virtual vmm = Memory::Virtual(CurCPU->CurrentProcess->PageTable); + bool PageAvailable = vmm.Check((void *)CheckPageFaultAddress); debug("Page available (Check(...)): %s. %s", PageAvailable ? "Yes" : "No", (params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result."); if (PageAvailable) { - bool Present = vma.Check((void *)CheckPageFaultAddress); - bool ReadWrite = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW); - bool User = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US); - bool WriteThrough = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT); - bool CacheDisabled = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD); - bool Accessed = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A); - bool Dirty = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D); - bool Global = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G); + bool Present = vmm.Check((void *)CheckPageFaultAddress); + bool ReadWrite = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW); + bool User = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US); + bool WriteThrough = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT); + bool CacheDisabled = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD); + bool Accessed = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A); + bool Dirty = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D); + bool Global = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G); /* ... */ debug("Page available: %s", Present ? "Yes" : "No"); diff --git a/Core/Crash/chfcts.hpp b/Core/Crash/chfcts.hpp index f5b0302..a891b64 100644 --- a/Core/Crash/chfcts.hpp +++ b/Core/Crash/chfcts.hpp @@ -37,7 +37,8 @@ struct CRData CPU::x64::CR4 cr4; CPU::x64::CR8 cr8; CPU::x64::EFER efer; - uintptr_t dr0, dr1, dr2, dr3, dr6; + uintptr_t dr0, dr1, dr2, dr3; + CPU::x64::DR6 dr6; CPU::x64::DR7 dr7; long ID; @@ -58,7 +59,8 @@ struct CRData CPU::x32::CR3 cr3; CPU::x32::CR4 cr4; CPU::x32::CR8 cr8; - uintptr_t dr0, dr1, dr2, dr3, dr6; + uintptr_t dr0, dr1, dr2, dr3; + CPU::x32::DR6 dr6; CPU::x32::DR7 dr7; long ID; diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 8f9244f..9545caa 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -31,7 +31,7 @@ static inline NIF void uart_wrapper(char c, void *unused) UNUSED(unused); } -static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function) +static inline NIF bool WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, va_list args) { const char *DbgLvlString; switch (Level) @@ -54,35 +54,52 @@ static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line, case DebugLevelFixme: DbgLvlString = "FIXME"; break; + case DebugLevelStub: + fctprintf(uart_wrapper, nullptr, "STUB | %s>%s() is stub\n", File, Function); + return false; + case DebugLevelFunction: + fctprintf(uart_wrapper, nullptr, "FUNC | %s>%s( ", File, Function); + vfctprintf(uart_wrapper, nullptr, Format, args); + fctprintf(uart_wrapper, nullptr, " )\n"); + return false; case DebugLevelUbsan: { DbgLvlString = "UBSAN"; fctprintf(uart_wrapper, nullptr, "%s| ", DbgLvlString); - return; + return true; } default: DbgLvlString = "UNKNW"; break; } - fctprintf(uart_wrapper, nullptr, "%s|%s->%s:%d: ", DbgLvlString, File, Function, Line); + fctprintf(uart_wrapper, nullptr, "%s| %s>%s:%d: ", DbgLvlString, File, Function, Line); + return true; } namespace SysDbg { NIF void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { - WritePrefix(Level, File, Line, Function); va_list args; va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } vfctprintf(uart_wrapper, nullptr, Format, args); va_end(args); } NIF void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { - WritePrefix(Level, File, Line, Function); va_list args; va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } vfctprintf(uart_wrapper, nullptr, Format, args); va_end(args); uart_wrapper('\n', nullptr); @@ -91,9 +108,13 @@ namespace SysDbg NIF void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { SmartTimeoutLock(DebuggerLock, 1000); - WritePrefix(Level, File, Line, Function); va_list args; va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } vfctprintf(uart_wrapper, nullptr, Format, args); va_end(args); } @@ -101,9 +122,13 @@ namespace SysDbg NIF void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { SmartTimeoutLock(DebuggerLock, 1000); - WritePrefix(Level, File, Line, Function); va_list args; va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } vfctprintf(uart_wrapper, nullptr, Format, args); va_end(args); uart_wrapper('\n', nullptr); @@ -113,9 +138,13 @@ namespace SysDbg // C compatibility extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { - WritePrefix(Level, File, Line, Function); va_list args; va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } vfctprintf(uart_wrapper, nullptr, Format, args); va_end(args); } @@ -123,9 +152,13 @@ extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Lin // C compatibility extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { - WritePrefix(Level, File, Line, Function); va_list args; va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } vfctprintf(uart_wrapper, nullptr, Format, args); va_end(args); uart_wrapper('\n', nullptr); @@ -135,9 +168,13 @@ extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { SmartTimeoutLock(DebuggerLock, 1000); - WritePrefix(Level, File, Line, Function); va_list args; va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } vfctprintf(uart_wrapper, nullptr, Format, args); va_end(args); } @@ -146,9 +183,13 @@ extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, i extern "C" NIF void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { SmartTimeoutLock(DebuggerLock, 1000); - WritePrefix(Level, File, Line, Function); va_list args; va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } vfctprintf(uart_wrapper, nullptr, Format, args); va_end(args); uart_wrapper('\n', nullptr); diff --git a/Core/Driver/Driver.cpp b/Core/Driver/Driver.cpp index 3c6ba29..fd99c57 100644 --- a/Core/Driver/Driver.cpp +++ b/Core/Driver/Driver.cpp @@ -216,7 +216,7 @@ namespace Driver } debug("Loading drivers from %s", Config.DriverDirectory); - foreach (auto DrvFile in DriverDirectory.node->Children) + foreach (auto DrvFile in DriverDirectory.GetChildren()) { if (DrvFile->Flags != VirtualFileSystem::NodeFlags::FILE) continue; diff --git a/Core/Lock.cpp b/Core/Lock.cpp index d4ce717..248c713 100644 --- a/Core/Lock.cpp +++ b/Core/Lock.cpp @@ -116,7 +116,7 @@ void LockClass::DeadLock(SpinLockData Lock) this->Unlock(); } - if (TaskManager) + if (TaskManager && !TaskManager->IsPanic()) TaskManager->Schedule(); } @@ -128,7 +128,13 @@ int LockClass::Lock(const char *FunctionName) Retry: int i = 0; while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000)) + { + /* FIXME */ + // if (TaskManager && !TaskManager->IsPanic()) + // TaskManager->Schedule(); + // else CPU::Pause(); + } if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000)) { @@ -187,7 +193,7 @@ void LockClass::TimeoutDeadLock(SpinLockData Lock, uint64_t Timeout) this->Unlock(); } - if (TaskManager) + if (TaskManager && !TaskManager->IsPanic()) TaskManager->Schedule(); } @@ -203,7 +209,13 @@ int LockClass::TimeoutLock(const char *FunctionName, uint64_t Timeout) Retry: int i = 0; while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000)) + { + /* FIXME */ + // if (TaskManager && !TaskManager->IsPanic()) + // TaskManager->Schedule(); + // else CPU::Pause(); + } if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000)) { diff --git a/Core/Memory/Memory.cpp b/Core/Memory/Memory.cpp index 6521319..ff04f17 100644 --- a/Core/Memory/Memory.cpp +++ b/Core/Memory/Memory.cpp @@ -441,7 +441,10 @@ void *malloc(size_t Size) break; } default: - throw; + { + error("Unknown allocator type %d", AllocatorType); + CPU::Stop(); + } } #ifdef DEBUG if (EnableExternalMemoryTracer) @@ -494,7 +497,10 @@ void *calloc(size_t n, size_t Size) return ret; } default: - throw; + { + error("Unknown allocator type %d", AllocatorType); + CPU::Stop(); + } } #ifdef DEBUG if (EnableExternalMemoryTracer) @@ -547,7 +553,10 @@ void *realloc(void *Address, size_t Size) return ret; } default: - throw; + { + error("Unknown allocator type %d", AllocatorType); + CPU::Stop(); + } } #ifdef DEBUG if (EnableExternalMemoryTracer) @@ -598,7 +607,10 @@ void free(void *Address) break; } default: - throw; + { + error("Unknown allocator type %d", AllocatorType); + CPU::Stop(); + } } #ifdef DEBUG if (EnableExternalMemoryTracer) diff --git a/Core/Memory/MemoryManager.cpp b/Core/Memory/MemoryManager.cpp index 1d4b4b5..c0da0b8 100644 --- a/Core/Memory/MemoryManager.cpp +++ b/Core/Memory/MemoryManager.cpp @@ -26,11 +26,14 @@ namespace Memory { if (!Size) Size = node->Length; - if (Offset > node->Length) + + if ((size_t)node->Offset > node->Length) return 0; - if (Offset + Size > node->Length) - Size = node->Length - Offset; - memcpy(Buffer, (uint8_t *)(node->Address + Offset), Size); + + if (node->Offset + Size > node->Length) + Size = node->Length - node->Offset; + + memcpy(Buffer, (uint8_t *)(node->Address + node->Offset), Size); return Size; } @@ -38,53 +41,21 @@ namespace Memory { if (!Size) Size = node->Length; - if (Offset > node->Length) + + if ((size_t)node->Offset > node->Length) return 0; - if (Offset + Size > node->Length) - Size = node->Length - Offset; - memcpy((uint8_t *)(node->Address + Offset), Buffer, Size); + + if (node->Offset + Size > node->Length) + Size = node->Length - node->Offset; + + memcpy((uint8_t *)(node->Address + node->Offset), Buffer, Size); return Size; } - SeekFSFunction(MEM_Seek) - { - long NewOffset; - - if (Whence == SEEK_SET) - { - if (Offset > node->Length) - return -1; - node->Offset = Offset; - NewOffset = (long)node->Offset; - } - else if (Whence == SEEK_CUR) - { - NewOffset = (long)(node->Offset + Offset); - if ((size_t)NewOffset > node->Length || NewOffset < 0) - return -1; - node->Offset = NewOffset; - } - else if (Whence == SEEK_END) - { - NewOffset = node->Length + Offset; - if (NewOffset < 0) - return -1; - node->Offset = NewOffset; - } - else - { - error("Invalid whence!"); - return -1; - } - - return NewOffset; - } - VirtualFileSystem::FileSystemOperations mem_op = { .Name = "mem", .Read = MEM_Read, .Write = MEM_Write, - .Seek = MEM_Seek, }; uint64_t MemMgr::GetAllocatedMemorySize() @@ -160,7 +131,10 @@ namespace Memory if (User) Flags |= Memory::PTFlag::US; - Memory::Virtual(this->Table).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), Flags); + void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE)); + + Memory::Virtual vmm = Memory::Virtual(this->Table); + vmm.Remap(AddressToMap, AddressToMap, Flags); } if (this->Directory) @@ -206,10 +180,12 @@ namespace Memory KernelAllocator.FreePages(Address, Count); + Memory::Virtual vmm = Memory::Virtual(this->Table); for (size_t i = 0; i < Count; i++) { - Memory::Virtual(this->Table).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), Memory::PTFlag::RW); - // Memory::Virtual(this->Table).Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE))); + void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE)); + vmm.Remap(AddressToMap, AddressToMap, Memory::PTFlag::RW); + // vmm.Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE))); } if (this->Directory) @@ -270,8 +246,11 @@ namespace Memory foreach (auto ap in AllocatedPagesList) { KernelAllocator.FreePages(ap.Address, ap.PageCount); + Memory::Virtual vmm = Memory::Virtual(this->Table); for (size_t i = 0; i < ap.PageCount; i++) - Memory::Virtual(this->Table).Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), (void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), Memory::PTFlag::RW); + vmm.Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), + (void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), + Memory::PTFlag::RW); } if (this->Directory) diff --git a/Core/Memory/PhysicalMemoryManager.cpp b/Core/Memory/PhysicalMemoryManager.cpp index fd59b40..3a2cdb4 100644 --- a/Core/Memory/PhysicalMemoryManager.cpp +++ b/Core/Memory/PhysicalMemoryManager.cpp @@ -120,6 +120,13 @@ namespace Memory return (void *)(PageBitmapIndex * PAGE_SIZE); } + if (TaskManager && !TaskManager->IsPanic()) + { + error("Out of memory! Killing current process..."); + TaskManager->KillProcess(TaskManager->GetCurrentProcess(), Tasking::KILL_OOM); + TaskManager->Schedule(); + } + error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory)); CPU::Stop(); __builtin_unreachable(); @@ -180,6 +187,13 @@ namespace Memory return (void *)(PageBitmapIndex * PAGE_SIZE); } + if (TaskManager && !TaskManager->IsPanic()) + { + error("Out of memory! Killing current process..."); + TaskManager->KillProcess(TaskManager->GetCurrentProcess(), Tasking::KILL_OOM); + TaskManager->Schedule(); + } + error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory)); CPU::Halt(true); __builtin_unreachable(); diff --git a/Core/PeripheralComponentInterconnect.cpp b/Core/PeripheralComponentInterconnect.cpp index c77e804..7633baf 100644 --- a/Core/PeripheralComponentInterconnect.cpp +++ b/Core/PeripheralComponentInterconnect.cpp @@ -957,11 +957,11 @@ namespace PCI { #if defined(a64) int Entries = s_cst(int, ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig)); - Memory::Virtual vma = Memory::Virtual(KernelPageTable); + Memory::Virtual vmm = Memory::Virtual(KernelPageTable); for (int t = 0; t < Entries; t++) { DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uintptr_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t)); - vma.Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW); + vmm.Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW); debug("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress, NewDeviceConfig->StartBus, NewDeviceConfig->EndBus); for (uintptr_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++) diff --git a/Core/UndefinedBehaviorSanitization.c b/Core/UndefinedBehaviorSanitization.c index 82303a9..83887f0 100644 --- a/Core/UndefinedBehaviorSanitization.c +++ b/Core/UndefinedBehaviorSanitization.c @@ -510,4 +510,4 @@ void __ubsan_handle_dynamic_type_cache_miss(struct dynamic_type_cache_miss_data ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); ubsan("Dynamic type cache miss."); UNUSED(ptr); -} \ No newline at end of file +} diff --git a/Execute/BinaryParse.cpp b/Execute/BinaryParse.cpp new file mode 100644 index 0000000..bfbf57d --- /dev/null +++ b/Execute/BinaryParse.cpp @@ -0,0 +1,171 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include + +#include "../kernel.h" +#include "../Fex.hpp" + +namespace Execute +{ + BinaryType GetBinaryType(void *Image) + { + Fex *FexHdr = (Fex *)Image; + Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)Image; + IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Image; + + /* Check Fex magic */ + if (FexHdr->Magic[0] == 'F' && + FexHdr->Magic[1] == 'E' && + FexHdr->Magic[2] == 'X' && + FexHdr->Magic[3] == '\0') + { + /* If the fex type is driver, we shouldn't return as Fex. */ + if (FexHdr->Type == FexFormatType::FexFormatType_Executable) + { + debug("Image - Fex"); + return BinaryType::BinTypeFex; + } + else if (FexHdr->Type == FexFormatType::FexFormatType_Driver) + { + debug("Fex Driver is not supposed to be executed."); + } + } + /* Check ELF magic. */ + else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 && + ELFHeader->e_ident[EI_MAG1] == ELFMAG1 && + ELFHeader->e_ident[EI_MAG2] == ELFMAG2 && + ELFHeader->e_ident[EI_MAG3] == ELFMAG3) + { + debug("Image - ELF"); + return BinaryType::BinTypeELF; + } + /* Every Windows executable starts with MZ header. */ + else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE) + { + IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Image) + MZHeader->e_lfanew); + IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Image) + MZHeader->e_lfanew); + + /* TODO: LE, EDOS */ + if (PEHeader->Signature == IMAGE_NT_SIGNATURE) + { + debug("Image - PE"); + return BinaryType::BinTypePE; + } + else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE) + { + debug("Image - NE"); + return BinaryType::BinTypeNE; + } + else + { + debug("Image - MZ"); + return BinaryType::BinTypeMZ; + } + } + + /* ... */ + return BinaryType::BinTypeUnknown; + } + + BinaryType GetBinaryType(char *Path) + { + BinaryType Type = BinaryType::BinTypeInvalid; + VirtualFileSystem::File ExFile = vfs->Open(Path); + + if (!ExFile.IsOK()) + { + vfs->Close(ExFile); + return Type; + } + + debug("File opened: %s", Path); + uint8_t *Buffer = new uint8_t[1024]; + vfs->Read(ExFile, Buffer, 128); + + Fex *FexHdr = (Fex *)Buffer; + Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)Buffer; + IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Buffer; + + /* Check Fex header. */ + if (FexHdr->Magic[0] == 'F' && + FexHdr->Magic[1] == 'E' && + FexHdr->Magic[2] == 'X' && + FexHdr->Magic[3] == '\0') + { + /* If the fex type is driver, we shouldn't return as Fex. */ + if (FexHdr->Type == FexFormatType::FexFormatType_Executable) + { + debug("Image - Fex"); + Type = BinaryType::BinTypeFex; + goto Success; + } + else if (FexHdr->Type == FexFormatType::FexFormatType_Driver) + { + fixme("Fex Driver is not supposed to be executed."); + /* TODO: Driver installation pop-up. */ + } + } + /* Check ELF header. */ + else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 && + ELFHeader->e_ident[EI_MAG1] == ELFMAG1 && + ELFHeader->e_ident[EI_MAG2] == ELFMAG2 && + ELFHeader->e_ident[EI_MAG3] == ELFMAG3) + { + debug("Image - ELF"); + Type = BinaryType::BinTypeELF; + goto Success; + } + /* Check MZ header. */ + else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE) + { + vfs->Seek(ExFile, MZHeader->e_lfanew, SEEK_SET); + vfs->Read(ExFile, Buffer, 512); + IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Buffer) + MZHeader->e_lfanew); + IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Buffer) + MZHeader->e_lfanew); + + /* TODO: LE, EDOS */ + if (PEHeader->Signature == IMAGE_NT_SIGNATURE) + { + debug("Image - PE"); + Type = BinaryType::BinTypePE; + goto Success; + } + else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE) + { + debug("Image - NE"); + Type = BinaryType::BinTypeNE; + goto Success; + } + else + { + debug("Image - MZ"); + Type = BinaryType::BinTypeMZ; + goto Success; + } + } + + /* ... */ + Type = BinaryType::BinTypeUnknown; + Success: + delete[] Buffer; + vfs->Close(ExFile); + return Type; + } +} diff --git a/Execute/Elf/BaseLoad.cpp b/Execute/Elf/BaseLoad.cpp deleted file mode 100644 index 398be11..0000000 --- a/Execute/Elf/BaseLoad.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include -#include -#include - -#include "../../kernel.h" -#include "../../Fex.hpp" - -using namespace Tasking; -using VirtualFileSystem::File; -using VirtualFileSystem::FileStatus; -using VirtualFileSystem::NodeFlags; - -namespace Execute -{ - struct InterpreterIPCDataLibrary - { - char Name[128]; - }; - - typedef struct - { - char Path[256]; - void *ElfFile; - void *MemoryImage; - struct InterpreterIPCDataLibrary Libraries[64]; - } InterpreterIPCData; - - /* Passing arguments as a sanity check and debugging. */ - void ELFInterpreterIPCThread(PCB *Process, char *Path, void *MemoryImage, void *ElfFile, std::vector NeededLibraries) - { - debug("Interpreter thread started for %s", Path); - // Interpreter will create an IPC with token "LOAD". - char UniqueToken[16] = {'L', 'O', 'A', 'D', '\0'}; - InterProcessCommunication::IPCHandle *Handle = nullptr; - while (Handle == nullptr) - { - debug("Searching for IPC with token %s", UniqueToken); - Handle = Process->IPC->SearchByToken(UniqueToken); - if (Handle == nullptr) - { - debug("Failed"); - } - - TaskManager->Sleep(200); - if (Handle == nullptr) - { - debug("Retrying..."); - } - } - debug("IPC found, sending data..."); - InterpreterIPCData *TmpBuffer = new InterpreterIPCData; - strcpy(TmpBuffer->Path, Path); - TmpBuffer->ElfFile = ElfFile; - TmpBuffer->MemoryImage = MemoryImage; - if (NeededLibraries.size() > 256) - warn("Too many libraries! (max 256)"); - for (size_t i = 0; i < NeededLibraries.size(); i++) - { - strcpy(TmpBuffer->Libraries[i].Name, NeededLibraries[i]); - } - -#ifdef DEBUG - debug("OUTSIDE DATA"); - debug("Path: %s", Path); - debug("ElfFile: %p", ElfFile); - debug("MemoryImage: %p", MemoryImage); - for (size_t i = 0; i < NeededLibraries.size(); i++) - { - debug("Library: %s", NeededLibraries[i]); - } - debug("INSIDE DATA"); - debug("Path: %s", TmpBuffer->Path); - debug("ElfFile: %p", TmpBuffer->ElfFile); - debug("MemoryImage: %p", TmpBuffer->MemoryImage); - for (size_t i = 0; i < NeededLibraries.size(); i++) - { - debug("Library: %s", TmpBuffer->Libraries[i].Name); - } -#endif - - RetryIPCWrite: - InterProcessCommunication::IPCErrorCode ret = Process->IPC->Write(Handle->ID, TmpBuffer, sizeof(InterpreterIPCData)); - debug("Write returned %d", ret); - if (ret == InterProcessCommunication::IPCErrorCode::IPCNotListening) - { - debug("IPC not listening, retrying..."); - TaskManager->Sleep(100); - goto RetryIPCWrite; - } - delete TmpBuffer; - /* Prevent race condition, maybe a - better idea is to watch when the - IPC is destroyed. */ - TaskManager->Sleep(5000); - TEXIT(0); - } - - PCB *InterpreterTargetProcess; - std::string *InterpreterTargetPath; /* We can't have String as a constructor :( */ - void *InterpreterMemoryImage; - void *InterpreterElfFile; - std::vector InterpreterNeededLibraries; - void ELFInterpreterThreadWrapper() - { - ELFInterpreterIPCThread(InterpreterTargetProcess, (char *)InterpreterTargetPath->c_str(), InterpreterMemoryImage, InterpreterElfFile, InterpreterNeededLibraries); - delete InterpreterTargetPath, InterpreterTargetPath = nullptr; - } - - ELFBaseLoad ELFLoad(char *Path, const char **argv, const char **envp, Tasking::TaskCompatibility Compatibility) - { - /* We get the base name ("app.elf") */ - const char *BaseName; - cwk_path_get_basename(Path, &BaseName, nullptr); - TaskArchitecture Arch = TaskArchitecture::UnknownArchitecture; - - File ExFile = vfs->Open(Path); - - if (ExFile.Status != FileStatus::OK) - { - vfs->Close(ExFile); - error("Failed to open file: %s", Path); - return {}; - } - else - { - if (ExFile.node->Flags != NodeFlags::FILE) - { - vfs->Close(ExFile); - error("Invalid file path: %s", Path); - return {}; - } - else if (GetBinaryType(Path) != BinaryType::BinTypeELF) - { - vfs->Close(ExFile); - error("Invalid file type: %s", Path); - return {}; - } - } - - size_t ExFileSize = ExFile.node->Length; - - /* Allocate elf in memory */ - void *ElfFile = KernelAllocator.RequestPages(TO_PAGES(ExFileSize + 1)); - /* Copy the file to the allocated memory */ - memcpy(ElfFile, (void *)ExFile.node->Address, ExFileSize); - debug("Elf file: %#lx - %#lx (length: %ld)", ElfFile, (uintptr_t)ElfFile + ExFileSize, ExFileSize); - - Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile; - - switch (ELFHeader->e_machine) - { - case EM_386: - Arch = TaskArchitecture::x32; - break; - case EM_X86_64: - Arch = TaskArchitecture::x64; - break; - case EM_ARM: - Arch = TaskArchitecture::ARM32; - break; - case EM_AARCH64: - Arch = TaskArchitecture::ARM64; - break; - default: - break; - } - - // TODO: This shouldn't be ignored - if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32) - { - if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB) - fixme("ELF32 LSB"); - else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB) - fixme("ELF32 MSB"); - else - fixme("ELF32 Unknown"); - } - else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64) - { - if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB) - fixme("ELF64 LSB"); - else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB) - fixme("ELF64 MSB"); - else - fixme("ELF64 Unknown"); - } - else - fixme("Unknown ELF"); - - /* ------------------------------------------------------------------------------------------------------------------------------ */ - - PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User, ElfFile); - Process->SetWorkingDirectory(vfs->GetNodeFromPath(Path)->Parent); - Memory::Virtual pV = Memory::Virtual(Process->PageTable); - for (size_t i = 0; i < TO_PAGES(ExFileSize); i++) - pV.Remap((void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)), (void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); - - // for (size_t i = 0; i < TO_PAGES(ElfLazyResolverSize); i++) - // pV.Remap((void *)((uintptr_t)ElfLazyResolver + (i * PAGE_SIZE)), (void *)((uintptr_t)ElfLazyResolver + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); - - ELFBaseLoad bl; - - switch (ELFHeader->e_type) - { - case ET_REL: - bl = ELFLoadRel(ElfFile, ExFile, Process); - break; - case ET_EXEC: - bl = ELFLoadExec(ElfFile, ExFile, Process); - break; - case ET_DYN: - bl = ELFLoadDyn(ElfFile, ExFile, Process); - break; - case ET_CORE: - { - fixme("ET_CORE not implemented"); - TaskManager->RevertProcessCreation(Process); - vfs->Close(ExFile); - return {}; - } - case ET_NONE: - default: - { - error("Unknown ELF Type: %d", ELFHeader->e_type); - vfs->Close(ExFile); - TaskManager->RevertProcessCreation(Process); - return {}; - } - } - - if (bl.Interpreter) - { - debug("ElfFile: %p ELFHeader: %p", ElfFile, ELFHeader); - - InterpreterTargetProcess = Process; - InterpreterTargetPath = new std::string(Path); /* We store in a String because Path may get changed while outside ELFLoad(). */ - InterpreterMemoryImage = bl.VirtualMemoryImage; - InterpreterElfFile = ElfFile; - InterpreterNeededLibraries = bl.NeededLibraries; - __sync; - TCB *InterpreterIPCThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)ELFInterpreterThreadWrapper); - InterpreterIPCThread->Rename("ELF Interpreter IPC Thread"); - InterpreterIPCThread->SetPriority(TaskPriority::Low); - } - - TCB *Thread = TaskManager->CreateThread(Process, - bl.InstructionPointer, - argv, envp, bl.auxv, - (IPOffset)0 /* ProgramHeader->p_offset */, // I guess I don't need this - Arch, - Compatibility); - - foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList()) - { - Thread->Memory->Add(p.Address, p.PageCount); - bl.TmpMem->DetachAddress(p.Address); - } - delete bl.TmpMem, bl.TmpMem = nullptr; - - bl.sd.Process = Process; - bl.sd.Thread = Thread; - bl.sd.Status = ExStatus::OK; - vfs->Close(ExFile); - return bl; - } -} diff --git a/Execute/Elf/ElfBaseLoad.cpp b/Execute/Elf/ElfBaseLoad.cpp new file mode 100644 index 0000000..ebccd4c --- /dev/null +++ b/Execute/Elf/ElfBaseLoad.cpp @@ -0,0 +1,187 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../../kernel.h" +#include "../../Fex.hpp" + +using namespace Tasking; +using VirtualFileSystem::File; +using VirtualFileSystem::FileStatus; +using VirtualFileSystem::NodeFlags; + +namespace Execute +{ + ELFBaseLoad ELFLoad(char *Path, + const char **argv, const char **envp, + TaskCompatibility Compatibility) + { + const char *BaseName; + cwk_path_get_basename(Path, &BaseName, nullptr); + TaskArchitecture Arch = TaskArchitecture::UnknownArchitecture; + + File ExFile = vfs->Open(Path); + + if (ExFile.Status != FileStatus::OK) + { + vfs->Close(ExFile); + error("Failed to open file: %s", Path); + return {}; + } + else if (ExFile.GetFlags() != NodeFlags::FILE) + { + vfs->Close(ExFile); + error("Invalid file path: %s", Path); + return {}; + } + else if (GetBinaryType(Path) != BinaryType::BinTypeELF) + { + vfs->Close(ExFile); + error("Invalid file type: %s", Path); + return {}; + } + + size_t ExFileSize = ExFile.GetLength(); + + void *ElfFile = KernelAllocator.RequestPages(TO_PAGES(ExFileSize + 1)); + vfs->Read(ExFile, (uint8_t *)ElfFile, ExFileSize); + debug("Loaded elf %s at %#lx with the length of %ld", + Path, ElfFile, ExFileSize); + + Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)ElfFile; + + switch (ELFHeader->e_machine) + { + case EM_386: + Arch = TaskArchitecture::x32; + break; + case EM_X86_64: + Arch = TaskArchitecture::x64; + break; + case EM_ARM: + Arch = TaskArchitecture::ARM32; + break; + case EM_AARCH64: + Arch = TaskArchitecture::ARM64; + break; + default: + break; + } + + // TODO: This shouldn't be ignored + if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32) + fixme("32-bit ELF"); + else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64) + fixme("64-bit ELF"); + else + fixme("Unknown class %d", ELFHeader->e_ident[EI_CLASS]); + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + if (ELFHeader->e_ident[EI_DATA] != ELFDATA2LSB) + { + fixme("ELF32 LSB expected, got %d", ELFHeader->e_ident[EI_DATA]); + } +#else + if (ELFHeader->e_ident[EI_DATA] != ELFDATA2MSB) + { + fixme("ELF32 MSB expected, got %d", ELFHeader->e_ident[EI_DATA]); + } +#endif + + /* ------------------------------------------------------------------------------------------------------------------------------ */ + + PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), + BaseName, TaskTrustLevel::User, ElfFile); + Process->SetWorkingDirectory(vfs->GetNodeFromPath(Path)->Parent); + Process->Info.Compatibility = TaskCompatibility::Native; + Process->Info.Architecture = TaskArchitecture::x64; + + ELFBaseLoad bl; + + ELFObject *obj = new ELFObject(Path, Process); + if (!obj->IsValid()) + { + error("Failed to load ELF object"); + vfs->Close(ExFile); + TaskManager->RevertProcessCreation(Process); + return {}; + } + + bl = obj->GetBaseLoadInfo(); + + /* TODO: Keep only the necessary headers */ + Memory::Virtual vmm = Memory::Virtual(Process->PageTable); + for (size_t i = 0; i < TO_PAGES(ExFileSize); i++) + { + void *AddressToMap = (void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)); + vmm.Remap(AddressToMap, AddressToMap, Memory::RW | Memory::US); + } + + if (bl.Interpreter) + { + debug("Keeping ElfFile at %p", ElfFile); + + TCB *InterIPCThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), + (IP)ELFInterpreterIPCThread, + nullptr, + nullptr, + std::vector(), + TaskArchitecture::x64, + TaskCompatibility::Native, + true); + + std::vector *tmp_needed_libs = + new std::vector(bl.NeededLibraries); + + InterIPCThread->SYSV_ABI_Call((uintptr_t)Process, + (uintptr_t) new std::string(Path), + (uintptr_t)bl.VirtualMemoryImage, + (uintptr_t)tmp_needed_libs); + + InterIPCThread->Rename("ELF Interpreter IPC Thread"); + InterIPCThread->SetPriority(TaskPriority::Low); + InterIPCThread->Status = TaskStatus::Ready; + } + + TCB *Thread = TaskManager->CreateThread(Process, + bl.InstructionPointer, + argv, envp, bl.auxv, + Arch, + Compatibility); + + foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList()) + { + Thread->Memory->Add(p.Address, p.PageCount); + bl.TmpMem->DetachAddress(p.Address); + } + delete bl.TmpMem, bl.TmpMem = nullptr; + + bl.sd.Process = Process; + bl.sd.Thread = Thread; + bl.sd.Status = ExStatus::OK; + vfs->Close(ExFile); + return bl; + } +} diff --git a/Execute/Elf/ElfInterpreter.cpp b/Execute/Elf/ElfInterpreter.cpp new file mode 100644 index 0000000..0dbe4bd --- /dev/null +++ b/Execute/Elf/ElfInterpreter.cpp @@ -0,0 +1,155 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include + +#include "../../kernel.h" + +using namespace Tasking; + +namespace Execute +{ + struct InterpreterIPCDataLibrary + { + char Name[64]; + }; + + typedef struct + { + char Path[256]; + void *MemoryImage; + struct InterpreterIPCDataLibrary Libraries[64]; + } InterpreterIPCData; + + void ELFInterpreterIPCThread(PCB *TargetProcess, + std::string *TargetPath, + void *MemoryImage, + std::vector *_NeededLibraries) + { + std::vector NeededLibraries = *_NeededLibraries; + delete _NeededLibraries; + + debug("Interpreter thread started for %s", TargetPath->c_str()); + // Interpreter will create an IPC with token "LOAD". + char UniqueToken[16] = {'L', 'O', 'A', 'D', '\0'}; + InterProcessCommunication::IPCHandle *Handle = nullptr; + while (Handle == nullptr) + { + debug("Searching for IPC with token %s", UniqueToken); + Handle = TargetProcess->IPC->SearchByToken(UniqueToken); + if (Handle == nullptr) + debug("Failed"); + + TaskManager->Sleep(200); + if (Handle == nullptr) + debug("Retrying..."); + } + debug("IPC found, sending data..."); + InterpreterIPCData *TmpBuffer = new InterpreterIPCData; + strncpy(TmpBuffer->Path, TargetPath->c_str(), sizeof(TmpBuffer->Path) - 1); + TmpBuffer->MemoryImage = MemoryImage; + size_t NeededLibsSize = NeededLibraries.size(); + + for (size_t i = 0; i < NeededLibsSize; i++) + strncpy(TmpBuffer->Libraries[i].Name, NeededLibraries[i], + sizeof(TmpBuffer->Libraries[i].Name) - 1); + +#ifdef DEBUG + debug("Input:"); + debug("Path: %s", TargetPath->c_str()); + debug("MemoryImage: %p", MemoryImage); + for (size_t i = 0; i < NeededLibsSize; i++) + debug("Library: %s", NeededLibraries[i]); + + debug("Buffer:"); + debug("Path: %s", TmpBuffer->Path); + debug("MemoryImage: %p", TmpBuffer->MemoryImage); + for (size_t i = 0; i < 64; i++) + { + if (TmpBuffer->Libraries[i].Name[0] != '\0') + break; + debug("Library: %s", TmpBuffer->Libraries[i].Name); + } +#endif + + RetryIPCWrite: + InterProcessCommunication::IPCErrorCode ret = + TargetProcess->IPC->Write(Handle->ID, TmpBuffer, sizeof(InterpreterIPCData)); + debug("Write returned %d", ret); + if (ret == InterProcessCommunication::IPCErrorCode::IPCNotListening) + { + debug("IPC not listening, retrying..."); + TaskManager->Sleep(100); + goto RetryIPCWrite; + } + delete TmpBuffer; + + while (!TargetProcess->IPC->SearchByToken(UniqueToken)) + TaskManager->Schedule(); + + debug("Interpreter thread finished for %s", TargetPath->c_str()); + + for (size_t i = 0; i < NeededLibsSize; i++) + delete[] NeededLibraries[i]; + + delete TargetPath; + TEXIT(0); + } + + uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, Memory::Virtual &vmm, const char *Interpreter) + { + if (GetBinaryType((char *)Interpreter) != BinaryType::BinTypeELF) + { + error("Interpreter \"%s\" is not an ELF file.", Interpreter); + return 0; + } + + /* No need to check if it's valid because + the function that calls this already checks it. */ + VirtualFileSystem::File ElfFile = vfs->Open(Interpreter); + + Elf64_Ehdr ELFHeader; + vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + debug("Interpreter type: %#x", ELFHeader.e_type); + + uintptr_t BaseAddress; + size_t ElfPHDRsSize; + + GetBaseAndSize(ElfFile, BaseAddress, ElfPHDRsSize); + MmImage MemoryImage = ELFCreateMemoryImage(mem, vmm, ElfFile, ElfPHDRsSize); + CopyLOADSegments(ElfFile, BaseAddress, (uintptr_t)MemoryImage.Physical); + vfs->Close(ElfFile); + + bool IsPIC = ELFHeader.e_type == ET_DYN; + debug("Elf %s PIC", IsPIC ? "is" : "is not"); + + if (IsPIC) + { + debug("Interpreter entry point: %#lx (%#lx + %#lx)", + (uintptr_t)MemoryImage.Physical + ELFHeader.e_entry, + (uintptr_t)MemoryImage.Physical, ELFHeader.e_entry); + + return (uintptr_t)MemoryImage.Physical + ELFHeader.e_entry; + } + else + { + debug("Interpreter entry point: %#lx", ELFHeader.e_entry); + return ELFHeader.e_entry; + } + } +} diff --git a/Execute/Elf/ElfLoader.cpp b/Execute/Elf/ElfLoader.cpp new file mode 100644 index 0000000..26badcb --- /dev/null +++ b/Execute/Elf/ElfLoader.cpp @@ -0,0 +1,480 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../../kernel.h" +#include "../../Fex.hpp" + +using namespace Tasking; +using namespace VirtualFileSystem; + +namespace Execute +{ + ELFBaseLoad ELFObject::LoadExec_x86_32(File &ElfFile, PCB *TargetProcess) + { + stub; + return {}; + } + + ELFBaseLoad ELFObject::LoadExec_x86_64(File &ElfFile, PCB *TargetProcess) + { + ELFBaseLoad ELFBase{}; + + uintptr_t BaseAddress; + size_t ElfPHDRsSize; + GetBaseAndSize(ElfFile, BaseAddress, ElfPHDRsSize); + + Elf64_Ehdr ELFHeader; + vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + uintptr_t EntryPoint = ELFHeader.e_entry; + debug("%s's entry point is %#lx", ElfFile.Name, EntryPoint); + + ELFBase.TmpMem = new Memory::MemMgr(TargetProcess->PageTable); /* This should be deleted inside BaseLoad.cpp */ + Memory::Virtual vmm(TargetProcess->PageTable); + + /* If required, MemoryImage will be at virtual address. (unless is PIC) + tl;dr this is where the code is stored. */ + MmImage MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, vmm, ElfFile, ElfPHDRsSize); + + debug("Solving symbols for %s", ElfFile.Name); + std::vector DynamicString = ELFGetSections_x86_64(ElfFile, ".dynstr"); + std::vector StringTable = ELFGetSections_x86_64(ElfFile, ".strtab"); + + if (DynamicString.size() < 1) /* TODO: check if this is required */ + DynamicString = StringTable; + + /* Calculate entry point */ + Elf64_Phdr FirstPhdr; + vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&FirstPhdr, sizeof(Elf64_Phdr)); + /* FIXME: this is not the correct way to calculate entry point */ + if (FirstPhdr.p_vaddr == 0) + { + debug("Entry point is null. Adding virtual address to entry point"); + EntryPoint += (uintptr_t)MemoryImage.Virtual; + } + + CopyLOADSegments(ElfFile, BaseAddress, (uintptr_t)MemoryImage.Physical); + + foreach (auto Tag in ELFGetDynamicTag_x86_64(ElfFile, DT_NEEDED)) + { + const char *ReqLib = new char[256]; + vfs->Seek(ElfFile, DynamicString[0].sh_offset + Tag.d_un.d_val, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)ReqLib, 256); + + debug("DT_NEEDED - %s", ReqLib); + ELFBase.NeededLibraries.push_back(ReqLib); + } + + char InterpreterPath[256] = {'\0'}; + std::vector PhdrINTERP = ELFGetSymbolType_x86_64(ElfFile, PT_INTERP); + foreach (auto Interp in PhdrINTERP) + { + const char *InterpPath = new char[256]; + vfs->Seek(ElfFile, Interp.p_offset, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)InterpPath, 256); + + memcpy((void *)InterpreterPath, InterpPath, + (strlen(InterpPath) > 256) ? 256 : strlen(InterpPath)); + debug("Interpreter: %s", InterpreterPath); + delete[] InterpPath; + + VirtualFileSystem::File InterpreterFile = vfs->Open(InterpreterPath); + if (!InterpreterFile.IsOK()) + { + warn("Failed to open interpreter file: %s", InterpreterPath); + vfs->Close(InterpreterFile); + continue; + } + else + { + if (GetBinaryType(InterpreterPath) != BinTypeELF) + { + warn("Interpreter %s is not an ELF file", InterpreterPath); + vfs->Close(InterpreterFile); + continue; + } + vfs->Close(InterpreterFile); + break; + } + } + + if (strlen(InterpreterPath) > 1) + { + EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, vmm, InterpreterPath); + ELFBase.Interpreter = true; + } + + debug("Entry Point: %#lx", EntryPoint); + + char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true); /* TODO: 4096 bytes is too much for this */ + strcpy(aux_platform, "x86_64"); + + ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)0 /* FIXME */}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage.Virtual}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader.e_phoff}}}); + + ELFBase.InstructionPointer = EntryPoint; + ELFBase.MemoryImage = MemoryImage.Physical; + ELFBase.VirtualMemoryImage = MemoryImage.Virtual; + + ELFBase.Success = true; + return ELFBase; + } + + ELFBaseLoad ELFObject::LoadDyn_x86_32(File &ElfFile, PCB *TargetProcess, bool IsLibrary) + { + stub; + return {}; + } + + ELFBaseLoad ELFObject::LoadDyn_x86_64(File &ElfFile, PCB *TargetProcess, bool IsLibrary) + { + ELFBaseLoad ELFBase{}; + + uintptr_t BaseAddress; + size_t ElfPHDRsSize; + GetBaseAndSize(ElfFile, BaseAddress, ElfPHDRsSize); + + Elf64_Ehdr ELFHeader; + vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + uintptr_t EntryPoint = ELFHeader.e_entry; + debug("%s's entry point is %#lx", ElfFile.Name, EntryPoint); + + ELFBase.TmpMem = new Memory::MemMgr(TargetProcess->PageTable); /* This should be deleted inside BaseLoad.cpp */ + Memory::Virtual vmm(TargetProcess->PageTable); + + /* If required, MemoryImage will be at virtual address. (unless is PIC) + tl;dr this is where the code is stored. */ + MmImage MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, vmm, ElfFile, ElfPHDRsSize); + + debug("Solving symbols for %s", ElfFile.Name); + std::vector DynamicString = ELFGetSections_x86_64(ElfFile, ".dynstr"); + std::vector StringTable = ELFGetSections_x86_64(ElfFile, ".strtab"); + + if (DynamicString.size() < 1) /* TODO: check if this is required */ + DynamicString = StringTable; + + /* Calculate entry point */ + Elf64_Phdr FirstPhdr; + vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&FirstPhdr, sizeof(Elf64_Phdr)); + /* FIXME: this is not the correct way to calculate entry point */ + if (FirstPhdr.p_vaddr == 0) + { + debug("Entry point is null. Adding virtual address to entry point"); + EntryPoint += (uintptr_t)MemoryImage.Virtual; + } + + CopyLOADSegments(ElfFile, BaseAddress, (uintptr_t)MemoryImage.Physical); + + foreach (auto Tag in ELFGetDynamicTag_x86_64(ElfFile, DT_NEEDED)) + { + const char *ReqLib = new char[256]; + vfs->Seek(ElfFile, DynamicString[0].sh_offset + Tag.d_un.d_val, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)ReqLib, 256); + + debug("DT_NEEDED - %s", ReqLib); + ELFBase.NeededLibraries.push_back(ReqLib); + } + + std::vector JmpRel = ELFGetDynamicTag_x86_64(ElfFile, DT_JMPREL); + std::vector SymTab = ELFGetDynamicTag_x86_64(ElfFile, DT_SYMTAB); + std::vector StrTab = ELFGetDynamicTag_x86_64(ElfFile, DT_STRTAB); + + if (JmpRel.size() < 1) + { + debug("No DT_JMPREL"); + } + + if (SymTab.size() < 1) + { + debug("No DT_SYMTAB"); + } + + if (StrTab.size() < 1) + { + debug("No DT_STRTAB"); + } + + if (JmpRel.size() > 1 && + SymTab.size() > 1 && + StrTab.size() > 1) + { + debug("JmpRel: %#lx, SymTab: %#lx, StrTab: %#lx", JmpRel[0].d_un.d_ptr, SymTab[0].d_un.d_ptr, StrTab[0].d_un.d_ptr); + Elf64_Rela *_JmpRel = (Elf64_Rela *)((uintptr_t)MemoryImage.Physical + (JmpRel[0].d_un.d_ptr - BaseAddress)); + Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)MemoryImage.Physical + (SymTab[0].d_un.d_ptr - BaseAddress)); + + char *_DynStr = (char *)((uintptr_t)MemoryImage.Physical + (StrTab[0].d_un.d_ptr - BaseAddress)); + + Elf64_Shdr *gotSection = nullptr; + Elf64_Shdr shdr; + for (Elf64_Half i = 0; i < ELFHeader.e_shnum; i++) + { + vfs->Seek(ElfFile, ELFHeader.e_shoff + i * sizeof(Elf64_Shdr), SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&shdr, sizeof(Elf64_Shdr)); + if (shdr.sh_type == SHT_PROGBITS && + (shdr.sh_flags & SHF_WRITE) && + (shdr.sh_flags & SHF_ALLOC)) + { + gotSection = new Elf64_Shdr; + *gotSection = shdr; + break; + } + } + + if (gotSection) + { + Elf64_Xword numEntries = gotSection->sh_size / sizeof(Elf64_Addr); + for (Elf64_Xword i = 0; i < numEntries - 3; i++) + { + Elf64_Rela *Rel = _JmpRel + i; + Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset + (uintptr_t)MemoryImage.Physical); + + Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info); + debug("r_offset: %#lx RelType: %d", Rel->r_offset, RelType); + + switch (RelType) + { + case R_X86_64_NONE: + break; + case R_X86_64_JUMP_SLOT: + { + Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info); + Elf64_Sym *Sym = _SymTab + SymIndex; + + if (Sym->st_name) + { + char *SymName = _DynStr + Sym->st_name; + debug("SymName: %s", SymName); + + Elf64_Sym LibSym = ELFLookupSymbol(ElfFile, SymName); + + if (LibSym.st_value) + { + *GOTEntry = (Elf64_Addr)((uintptr_t)MemoryImage.Physical + LibSym.st_value); + debug("GOT[%ld]: %#lx + %#lx = %#lx", + i, (uintptr_t)MemoryImage.Physical, LibSym.st_value, *GOTEntry); + } + } + break; + } + default: + { + fixme("RelType %d not supported", RelType); + break; + } + } + + debug("GOT[%ld](%#lx): %#lx", i, GOTEntry, *GOTEntry); + } + + delete gotSection; + } + else + { + debug("GOT section not found"); + } + } + + /* ------------------------------------------------------------------------ */ + + foreach (auto Tag in ELFGetDynamicTag_x86_64(ElfFile, DT_NEEDED)) + { + const char *ReqLib = new char[256]; + vfs->Seek(ElfFile, DynamicString[0].sh_offset + Tag.d_un.d_val, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)ReqLib, 256); + + debug("DT_NEEDED - %s", ReqLib); + ELFBase.NeededLibraries.push_back(ReqLib); + } + + char InterpreterPath[256] = {'\0'}; + std::vector PhdrINTERP = ELFGetSymbolType_x86_64(ElfFile, PT_INTERP); + foreach (auto Interp in PhdrINTERP) + { + const char *InterpPath = new char[256]; + vfs->Seek(ElfFile, Interp.p_offset, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)InterpPath, 256); + + memcpy((void *)InterpreterPath, InterpPath, + (strlen(InterpPath) > 256) ? 256 : strlen(InterpPath)); + debug("Interpreter: %s", InterpreterPath); + delete[] InterpPath; + + VirtualFileSystem::File InterpreterFile = vfs->Open(InterpreterPath); + if (!InterpreterFile.IsOK()) + { + warn("Failed to open interpreter file: %s", InterpreterPath); + vfs->Close(InterpreterFile); + continue; + } + else + { + if (GetBinaryType(InterpreterPath) != BinTypeELF) + { + warn("Interpreter %s is not an ELF file", InterpreterPath); + vfs->Close(InterpreterFile); + continue; + } + vfs->Close(InterpreterFile); + break; + } + } + + if (strlen(InterpreterPath) > 1) + { + EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, vmm, InterpreterPath); + ELFBase.Interpreter = true; + } + else if (IsLibrary) + { + /* FIXME: Detect interpreter from current running process. */ + EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, vmm, "/lib/ld.so"); + ELFBase.Interpreter = true; + } + + debug("Entry Point: %#lx", EntryPoint); + + char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true); /* TODO: 4096 bytes is too much for this */ + strcpy(aux_platform, "x86_64"); + + ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)0 /* FIXME */}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage.Virtual}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}}); + ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader.e_phoff}}}); + + ELFBase.InstructionPointer = EntryPoint; + ELFBase.MemoryImage = MemoryImage.Physical; + ELFBase.VirtualMemoryImage = MemoryImage.Virtual; + + ELFBase.Success = true; + return ELFBase; + } + + ELFObject::ELFObject(char *AbsolutePath, + PCB *TargetProcess, + bool IsLibrary) + { + if (GetBinaryType(AbsolutePath) != BinaryType::BinTypeELF) + { + error("%s is not an ELF file or is invalid.", AbsolutePath); + return; + } + + VirtualFileSystem::File ExFile = vfs->Open(AbsolutePath); + + Elf32_Ehdr ELFHeader; + vfs->Read(ExFile, (uint8_t *)&ELFHeader, sizeof(Elf32_Ehdr)); + + ELFBaseLoad bl; + switch (ELFHeader.e_type) + { + case ET_REL: + { + fixme("ET_REL not implemented"); + break; + } + case ET_EXEC: + { + switch (ELFHeader.e_machine) + { + case EM_386: + this->BaseLoadInfo = this->LoadExec_x86_32(ExFile, + TargetProcess); + break; + case EM_X86_64: + this->BaseLoadInfo = this->LoadExec_x86_64(ExFile, + TargetProcess); + break; + case EM_ARM: + error("ARM is not supported yet!"); + break; + case EM_AARCH64: + error("ARM64 is not supported yet!"); + break; + default: + error("Unknown architecture: %d", ELFHeader.e_machine); + break; + } + break; + } + case ET_DYN: + { + switch (ELFHeader.e_machine) + { + case EM_386: + this->BaseLoadInfo = this->LoadDyn_x86_32(ExFile, + TargetProcess, + IsLibrary); + break; + case EM_X86_64: + this->BaseLoadInfo = this->LoadDyn_x86_64(ExFile, + TargetProcess, + IsLibrary); + break; + case EM_ARM: + error("ARM is not supported yet!"); + break; + case EM_AARCH64: + error("ARM64 is not supported yet!"); + break; + default: + error("Unknown architecture: %d", ELFHeader.e_machine); + break; + } + break; + } + case ET_CORE: + { + fixme("ET_CORE not implemented"); + break; + } + case ET_NONE: + default: + { + error("Unknown ELF Type: %d", ELFHeader.e_type); + break; + } + } + + vfs->Close(ExFile); + } + + ELFObject::~ELFObject() + { + } +} diff --git a/Execute/Elf/ElfParse.cpp b/Execute/Elf/ElfParse.cpp new file mode 100644 index 0000000..7858ad5 --- /dev/null +++ b/Execute/Elf/ElfParse.cpp @@ -0,0 +1,340 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include + +#include "../../kernel.h" +#include "../../Fex.hpp" + +namespace Execute +{ + bool ELFIs64(void *Header) + { + Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)Header; + if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64) + return true; + return false; + } + + /* Originally from https://wiki.osdev.org/ELF_Tutorial */ + + Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header) + { + return (Elf64_Shdr *)((uintptr_t)Header + Header->e_shoff); + } + + Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index) + { + return &GetELFSheader(Header)[Index]; + } + + char *GetELFStringTable(Elf64_Ehdr *Header) + { + if (Header->e_shstrndx == SHN_UNDEF) + return nullptr; + return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset; + } + + char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset) + { + char *StringTable = GetELFStringTable(Header); + if (StringTable == nullptr) + return nullptr; + return StringTable + Offset; + } + + Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name) + { + Elf64_Shdr *SymbolTable = nullptr; + Elf64_Shdr *StringTable = nullptr; + + for (Elf64_Half i = 0; i < Header->e_shnum; i++) + { + Elf64_Shdr *shdr = GetELFSection(Header, i); + switch (shdr->sh_type) + { + case SHT_SYMTAB: + SymbolTable = shdr; + StringTable = GetELFSection(Header, shdr->sh_link); + break; + default: + { + break; + } + } + } + + if (SymbolTable == nullptr || StringTable == nullptr) + return nullptr; + + for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++) + { + Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym))); + char *String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name); + if (strcmp(String, Name) == 0) + return Symbol; + } + return nullptr; + } + + Elf64_Sym ELFLookupSymbol(VirtualFileSystem::File &ElfFile, const char *Name) + { + off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); + + Elf64_Ehdr Header; + vfs->Seek(ElfFile, 0, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&Header, sizeof(Elf64_Ehdr)); + + Elf64_Shdr SymbolTable; + Elf64_Shdr StringTable; + + for (Elf64_Half i = 0; i < Header.e_shnum; i++) + { + Elf64_Shdr shdr; + vfs->Seek(ElfFile, Header.e_shoff + (i * sizeof(Elf64_Shdr)), SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&shdr, sizeof(Elf64_Shdr)); + + switch (shdr.sh_type) + { + case SHT_SYMTAB: + SymbolTable = shdr; + vfs->Seek(ElfFile, Header.e_shoff + (shdr.sh_link * sizeof(Elf64_Shdr)), SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&StringTable, sizeof(Elf64_Shdr)); + break; + default: + { + break; + } + } + } + + if (SymbolTable.sh_name == 0 || + StringTable.sh_name == 0) + { + error("Symbol table not found."); + vfs->Seek(ElfFile, OldOffset, SEEK_SET); + return {}; + } + + for (size_t i = 0; i < (SymbolTable.sh_size / sizeof(Elf64_Sym)); i++) + { + // Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym))); + Elf64_Sym Symbol; + vfs->Seek(ElfFile, SymbolTable.sh_offset + (i * sizeof(Elf64_Sym)), SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&Symbol, sizeof(Elf64_Sym)); + + // char *String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name); + char String[256]; + vfs->Seek(ElfFile, StringTable.sh_offset + Symbol.st_name, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&String, 256); + + if (strcmp(String, Name) == 0) + { + vfs->Seek(ElfFile, OldOffset, SEEK_SET); + return Symbol; + } + } + error("Symbol not found."); + vfs->Seek(ElfFile, OldOffset, SEEK_SET); + return {}; + } + + uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index) + { +#if defined(a64) + if (Table == SHN_UNDEF || Index == SHN_UNDEF) + return 0; + Elf64_Shdr *SymbolTable = GetELFSection(Header, Table); + + uint64_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize; + if (Index >= STEntries) + { + error("Symbol index out of range %d-%u.", Table, Index); + return 0xdead; + } + + uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset; + Elf64_Sym *Symbol = &((Elf64_Sym *)SymbolAddress)[Index]; + + if (Symbol->st_shndx == SHN_UNDEF) + { + Elf64_Shdr *StringTable = GetELFSection(Header, SymbolTable->sh_link); + const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name; + + void *Target = (void *)ELFLookupSymbol(Header, Name)->st_value; + if (Target == nullptr) + { + if (ELF64_ST_BIND(Symbol->st_info) & STB_WEAK) + return 0; + else + { + error("Undefined external symbol \"%s\".", Name); + return 0xdead; + } + } + else + return (uintptr_t)Target; + } + else if (Symbol->st_shndx == SHN_ABS) + return Symbol->st_value; + else + { + Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx); + return (uintptr_t)Header + Symbol->st_value + Target->sh_offset; + } +#endif + } + + void CopyLOADSegments(VirtualFileSystem::File &ElfFile, uintptr_t HdrsBase, uintptr_t PhysicalBase) + { + off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); + + Elf64_Ehdr ELFHeader; + vfs->Seek(ElfFile, 0, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + + Elf64_Phdr ProgramHeaders; + for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) + { + vfs->Seek(ElfFile, ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); + if (ProgramHeaders.p_type != PT_LOAD) + continue; + + uintptr_t SegmentDestination = (ProgramHeaders.p_vaddr - HdrsBase) + PhysicalBase; + + debug("Copying segment to %#lx (%ld file bytes, %ld mem bytes)", + SegmentDestination, + ProgramHeaders.p_filesz, ProgramHeaders.p_memsz); + + if (ProgramHeaders.p_filesz > 0) + { + vfs->Seek(ElfFile, ProgramHeaders.p_offset, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)SegmentDestination, ProgramHeaders.p_filesz); + } + + if (ProgramHeaders.p_memsz - ProgramHeaders.p_filesz > 0) + memset((void *)(SegmentDestination + ProgramHeaders.p_filesz), + 0, + ProgramHeaders.p_memsz - ProgramHeaders.p_filesz); + } + + vfs->Seek(ElfFile, OldOffset, SEEK_SET); + } + + void GetBaseAndSize(VirtualFileSystem::File &ElfFile, uintptr_t &Base, size_t &Size) + { + Base = UINTPTR_MAX; + Size = 0; + + off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); + + Elf64_Ehdr ELFHeader; + vfs->Seek(ElfFile, 0, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + + Elf64_Phdr ProgramHeaders; + vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); + + for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) + { + Base = MIN(Base, ProgramHeaders.p_vaddr); + uintptr_t SegmentEnd = ProgramHeaders.p_vaddr - Base + ProgramHeaders.p_memsz; + Size = MAX(Size, SegmentEnd); + + vfs->Seek(ElfFile, sizeof(Elf64_Phdr), SEEK_CUR); + vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); + } + debug("Base: %#lx, Size: %#lx (%ld, %ld KB)", Base, Size, Size, TO_KB(Size)); + vfs->Seek(ElfFile, OldOffset, SEEK_SET); + } + + MmImage ELFCreateMemoryImage(Memory::MemMgr *mem, + Memory::Virtual &vmm, + VirtualFileSystem::File &ElfFile, + size_t Length) + { + off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); + + void *MemoryImage = nullptr; + Elf64_Ehdr ELFHeader; + vfs->Seek(ElfFile, 0, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + + bool IsPIC = ELFHeader.e_type == ET_DYN; + UNUSED(IsPIC); + debug("Elf %s PIC", IsPIC ? "is" : "is not"); + + bool FirstProgramHeader = false; + uintptr_t FirstProgramHeaderVirtualAddress = 0x0; + + Elf64_Phdr ProgramHeaders; + for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) + { + vfs->Seek(ElfFile, ELFHeader.e_phoff + i * sizeof(Elf64_Phdr), SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); + if (ProgramHeaders.p_type != PT_LOAD) + continue; + + if (!FirstProgramHeader) + { + FirstProgramHeader = true; + FirstProgramHeaderVirtualAddress = ProgramHeaders.p_vaddr; + } + + if (ProgramHeaders.p_vaddr == 0) + { + debug("p_vaddr is 0, allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length); + MemoryImage = mem->RequestPages(TO_PAGES(Length), true); + debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length); + memset(MemoryImage, 0, Length); + + vfs->Seek(ElfFile, OldOffset, SEEK_SET); + return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress}; + } + } + + debug("Allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length); + MemoryImage = mem->RequestPages(TO_PAGES(Length)); + debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length); + memset(MemoryImage, 0, Length); + + uintptr_t FirstProgramHeaderVirtualAddressAligned = 0; + + if (FirstProgramHeaderVirtualAddress != 0) + { + FirstProgramHeaderVirtualAddressAligned = ALIGN_DOWN(FirstProgramHeaderVirtualAddress, PAGE_SIZE); + debug("Aligning address %#lx to %#lx", + FirstProgramHeaderVirtualAddress, + FirstProgramHeaderVirtualAddressAligned); + } + else + FirstProgramHeaderVirtualAddress = (uintptr_t)MemoryImage; + + for (size_t i = 0; i < TO_PAGES(Length); i++) + { + vmm.Remap((void *)((uintptr_t)FirstProgramHeaderVirtualAddressAligned + (i * PAGE_SIZE)), (void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); + debug("Remapped: %#lx -> %#lx", (uintptr_t)FirstProgramHeaderVirtualAddressAligned + (i * PAGE_SIZE), (uintptr_t)MemoryImage + (i * PAGE_SIZE)); + } + + vfs->Seek(ElfFile, OldOffset, SEEK_SET); + return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress}; + } +} diff --git a/Execute/Elf/Rel.cpp b/Execute/Elf/ElfRel.cpp similarity index 98% rename from Execute/Elf/Rel.cpp rename to Execute/Elf/ElfRel.cpp index 3417513..52b2377 100644 --- a/Execute/Elf/Rel.cpp +++ b/Execute/Elf/ElfRel.cpp @@ -27,11 +27,11 @@ namespace Execute /* Originally from https://wiki.osdev.org/ELF_Tutorial */ ELFBaseLoad ELFLoadRel(void *BaseImage, - VirtualFileSystem::File &ExFile, + const char *Name, Tasking::PCB *Process) { #if defined(a64) - UNUSED(ExFile); + UNUSED(Name); debug("Relocatable"); /* TODO: I have to fully implement this, but for now I will leave it as it is now. */ warn("Relocatable ELF is not fully supported yet"); diff --git a/Execute/Elf/ElfSharedObjects.cpp b/Execute/Elf/ElfSharedObjects.cpp new file mode 100644 index 0000000..516d26c --- /dev/null +++ b/Execute/Elf/ElfSharedObjects.cpp @@ -0,0 +1,159 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG +#include +#endif + +#include "../../kernel.h" +#include "../../Fex.hpp" + +using namespace Tasking; + +NewLock(ExecuteServiceLock); + +namespace Execute +{ + Memory::MemMgr *mem = nullptr; + std::vector Libs; + + void LibraryManagerService() + { + mem = new Memory::MemMgr; + + while (true) + { + { + SmartLock(ExecuteServiceLock); + foreach (auto &Lib in Libs) + { + if (Lib.RefCount > 0) + { + Lib.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes); + debug("Reset timeout for %s", Lib.Identifier); + continue; + } + if (Lib.Timeout < TimeManager->GetCounter()) + { + // TODO: Remove library from memory + fixme("Removed library %s because of timeout", Lib.Identifier); + } + else + { + debug("Timeout for %s is %ld", Lib.Identifier, Lib.Timeout); + } + } + debug("Waiting 10 seconds..."); + } + TaskManager->Sleep(10000); + } + } + + bool AddLibrary(char *Identifier, + VirtualFileSystem::File &ExFile, + const Memory::Virtual &vmm) + { + SmartLock(ExecuteServiceLock); + SharedLibrary sl; + + foreach (auto lib in Libs) + { + if (strcmp(lib.Identifier, Identifier) == 0) + { + debug("Library %s already loaded", Identifier); + lib.RefCount++; + return true; + } + } + + PCB *Process = TaskManager->GetCurrentProcess(); + ELFObject *obj = new ELFObject(vfs->GetPathFromNode(ExFile.GetNode()).get(), Process, true); + if (!obj->IsValid()) + { + error("Failed to load dynamic ELF"); + return false; + } + ELFBaseLoad bl = obj->GetBaseLoadInfo(); + + strncpy(sl.Identifier, Identifier, sizeof(sl.Identifier) - 1); + char *AbsolutePath = vfs->GetPathFromNode(ExFile.GetNode()).get(); + strncpy(sl.Path, AbsolutePath, sizeof(sl.Path) - 1); + sl.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes); + sl.RefCount = 0; + sl.MemoryImage = (uintptr_t)bl.MemoryImage; + sl.Length = ExFile.GetLength(); + Libs.push_back(sl); + debug("Library %s loaded at %#lx", Identifier, sl.MemoryImage); + + if (bl.InstructionPointer) + { + TCB *Thread = TaskManager->CreateThread(Process, + bl.InstructionPointer, + nullptr, + nullptr, + bl.auxv, + Process->Info.Architecture, + Process->Info.Compatibility, + true); + Thread->Rename(Identifier); + Thread->Status = TaskStatus::Ready; + + foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList()) + { + Thread->Memory->Add(p.Address, p.PageCount); + bl.TmpMem->DetachAddress(p.Address); + } + } + else + { + foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList()) + { + /* FIXME: MEMORY LEAK */ + // Process->Memory->Add(p.Address, p.PageCount); + bl.TmpMem->DetachAddress(p.Address); + fixme("Potential memory leak. (%#lx - %ld)", + p.Address, p.PageCount); + } + } + return true; + } + + SharedLibrary GetLibrary(char *Identifier) + { + SmartLock(ExecuteServiceLock); + foreach (auto Lib in Libs) + { + if (strcmp(Lib.Identifier, Identifier) == 0) + { + Lib.RefCount++; + debug("Library %s found at %#lx", Identifier, Lib.MemoryImage); + return Lib; + } + } + error("Library %s not found", Identifier); + return SharedLibrary(); + } +} diff --git a/Execute/Elf/Exec.cpp b/Execute/Elf/Exec.cpp deleted file mode 100644 index 8c2098e..0000000 --- a/Execute/Elf/Exec.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include -#include -#include - -#include "../../kernel.h" -#include "../../Fex.hpp" - -using namespace Tasking; - -namespace Execute -{ - ELFBaseLoad ELFLoadExec(void *ElfFile, - VirtualFileSystem::File &ExFile, - Tasking::PCB *Process) - { -#if defined(a64) - debug("Executable"); - ELFBaseLoad ELFBase = {}; - /* This should be deleted inside BaseLoad.cpp */ - ELFBase.TmpMem = new Memory::MemMgr(Process->PageTable); - - Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile; - Memory::Virtual pV(Process->PageTable); - - uintptr_t BaseAddress = UINTPTR_MAX; - uint64_t ElfAppSize = 0; - uintptr_t EntryPoint = ELFHeader->e_entry; - debug("%s's entry point is %#lx", ExFile.Name, EntryPoint); - - Elf64_Phdr ItrPhdr; - - /* Get base address */ - for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) - { - memcpy(&ItrPhdr, - (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, - sizeof(Elf64_Phdr)); - - BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr); - } - - /* Get size */ - for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) - { - memcpy(&ItrPhdr, - (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, - sizeof(Elf64_Phdr)); - - uintptr_t SegmentEnd; - SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz; - ElfAppSize = MAX(ElfAppSize, SegmentEnd); - } - debug("BaseAddress: %#lx | ElfAppSize: %#lx (%ld, %ld KB)", BaseAddress, ElfAppSize, ElfAppSize, TO_KB(ElfAppSize)); - - /* If required, MemoryImage will be at virtual address. (unless has PIE) - * - * tl;dr this is where the code is stored. */ - MmImage MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, pV, ElfFile, ElfAppSize); - - debug("Solving symbols for address: %#llx", (uintptr_t)ElfFile); - Elf64_Shdr *ElfSections = (Elf64_Shdr *)((uintptr_t)ElfFile + ELFHeader->e_shoff); - Elf64_Shdr *DynamicString = nullptr; - Elf64_Shdr *StringTable = nullptr; - - for (Elf64_Half i = 0; i < ELFHeader->e_shnum; i++) - { - char *DynamicStringTable = (char *)((uintptr_t)ElfFile + ElfSections[ELFHeader->e_shstrndx].sh_offset + ElfSections[i].sh_name); - - if (strcmp(DynamicStringTable, ".dynstr") == 0) - { - DynamicString = &ElfSections[i]; - debug("Found .dynstr"); - } - else if (strcmp(DynamicStringTable, ".strtab") == 0) - { - StringTable = &ElfSections[i]; - debug("Found .strtab"); - } - } - - if (!DynamicString) - DynamicString = StringTable; - - /* Calculate entry point */ - memcpy(&ItrPhdr, (uint8_t *)ElfFile + ELFHeader->e_phoff, sizeof(Elf64_Phdr)); - if (ItrPhdr.p_vaddr == 0) - EntryPoint += (uintptr_t)MemoryImage.Virtual; - - char InterpreterPath[256] = {'\0'}; - - for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) - { - memcpy(&ItrPhdr, - (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, - sizeof(Elf64_Phdr)); - - switch (ItrPhdr.p_type) - { - case PT_NULL: - fixme("PT_NULL"); - break; - case PT_LOAD: - { - debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx", - ItrPhdr.p_offset, ItrPhdr.p_vaddr, - ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align); - uintptr_t MAddr = (ItrPhdr.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage.Physical; - fixme("Address: %#lx %s%s%s", MAddr, - (ItrPhdr.p_flags & PF_R) ? "R" : "", - (ItrPhdr.p_flags & PF_W) ? "W" : "", - (ItrPhdr.p_flags & PF_X) ? "X" : ""); - - memcpy((void *)MAddr, (uint8_t *)ElfFile + ItrPhdr.p_offset, ItrPhdr.p_filesz); - debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)ElfFile + ItrPhdr.p_offset, MAddr, ItrPhdr.p_filesz); - break; - } - case PT_DYNAMIC: - { - debug("PT_DYNAMIC - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx", - ItrPhdr.p_offset, ItrPhdr.p_vaddr, - ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align); - - Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)ElfFile + ItrPhdr.p_offset); - - for (size_t i = 0; i < ItrPhdr.p_filesz / sizeof(Elf64_Dyn); i++) - { - if (Dynamic[i].d_tag == DT_NEEDED) - { - if (!DynamicString) - { - error("DynamicString is null"); - break; - } - - const char *ReqLib = (const char *)((uintptr_t)ElfFile + DynamicString->sh_offset + Dynamic[i].d_un.d_val); - debug("DT_NEEDED - Name[%ld]: %s", i, ReqLib); - ELFBase.NeededLibraries.push_back(ReqLib); - } - else if (Dynamic[i].d_tag == DT_NULL) - break; - } - break; - } - case PT_INTERP: - { - debug("PT_INTERP - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx", - ItrPhdr.p_offset, ItrPhdr.p_vaddr, - ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align); - - memcpy((void *)InterpreterPath, (uint8_t *)ElfFile + ItrPhdr.p_offset, 256); - debug("Interpreter: %s", InterpreterPath); - - VirtualFileSystem::File InterpreterFile = vfs->Open(InterpreterPath); - if (!InterpreterFile.IsOK()) - warn("Failed to open interpreter file: %s", InterpreterPath); - - vfs->Close(InterpreterFile); - break; - } - /* ... */ - case PT_PHDR: - { - fixme("PT_PHDR - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx", - ItrPhdr.p_offset, ItrPhdr.p_vaddr, - ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align); - break; - } - default: - { - warn("Unknown or unsupported program header type: %d", ItrPhdr.p_type); - break; - } - } - } - - if (strlen(InterpreterPath) > 1) - { - EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, pV, InterpreterPath); - ELFBase.Interpreter = true; - } - - debug("Entry Point: %#lx", EntryPoint); - - char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true); - strcpy(aux_platform, "x86_64"); - - ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)vfs->GetPathFromNode(ExFile.node).get()}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage.Virtual}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}}); - - ELFBase.InstructionPointer = EntryPoint; - ELFBase.MemoryImage = MemoryImage.Physical; - ELFBase.VirtualMemoryImage = MemoryImage.Virtual; - - ELFBase.Success = true; - return ELFBase; -#elif defined(a32) - return {}; -#endif - } -} diff --git a/Execute/Elf/Parse.cpp b/Execute/Elf/Parse.cpp deleted file mode 100644 index fca94cc..0000000 --- a/Execute/Elf/Parse.cpp +++ /dev/null @@ -1,330 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include - -#include "../../kernel.h" -#include "../../Fex.hpp" - -namespace Execute -{ - /* Originally from https://wiki.osdev.org/ELF_Tutorial */ - - Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header) - { - return (Elf64_Shdr *)((uintptr_t)Header + Header->e_shoff); - } - - Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index) - { - return &GetELFSheader(Header)[Index]; - } - - char *GetELFStringTable(Elf64_Ehdr *Header) - { - if (Header->e_shstrndx == SHN_UNDEF) - return nullptr; - return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset; - } - - char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset) - { - char *StringTable = GetELFStringTable(Header); - if (StringTable == nullptr) - return nullptr; - return StringTable + Offset; - } - - Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name) - { -#if defined(a64) - Elf64_Shdr *SymbolTable = nullptr; - Elf64_Shdr *StringTable = nullptr; - Elf64_Sym *Symbol = nullptr; - char *String = nullptr; - - for (Elf64_Half i = 0; i < Header->e_shnum; i++) - { - Elf64_Shdr *shdr = GetELFSection(Header, i); - switch (shdr->sh_type) - { - case SHT_SYMTAB: - SymbolTable = shdr; - StringTable = GetELFSection(Header, shdr->sh_link); - break; - default: - { - break; - } - } - } - - if (SymbolTable == nullptr || StringTable == nullptr) - return nullptr; - - for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++) - { - Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym))); - String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name); - if (strcmp(String, Name) == 0) - return Symbol; - } -#elif defined(a32) -#endif - return nullptr; - } - - uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index) - { -#if defined(a64) - if (Table == SHN_UNDEF || Index == SHN_UNDEF) - return 0; - Elf64_Shdr *SymbolTable = GetELFSection(Header, Table); - - uint64_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize; - if (Index >= STEntries) - { - error("Symbol index out of range %d-%u.", Table, Index); - return 0xdead; - } - - uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset; - Elf64_Sym *Symbol = &((Elf64_Sym *)SymbolAddress)[Index]; - - if (Symbol->st_shndx == SHN_UNDEF) - { - Elf64_Shdr *StringTable = GetELFSection(Header, SymbolTable->sh_link); - const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name; - - void *Target = (void *)ELFLookupSymbol(Header, Name)->st_value; - if (Target == nullptr) - { - if (ELF64_ST_BIND(Symbol->st_info) & STB_WEAK) - return 0; - else - { - error("Undefined external symbol \"%s\".", Name); - return 0xdead; - } - } - else - return (uintptr_t)Target; - } - else if (Symbol->st_shndx == SHN_ABS) - return Symbol->st_value; - else - { - Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx); - return (uintptr_t)Header + Symbol->st_value + Target->sh_offset; - } -#elif defined(a32) - return 0; -#endif - } - - Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag) - { -#if defined(a64) - Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile; - - Elf64_Phdr ItrPhdr; - for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) - { - memcpy(&ItrPhdr, (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr)); - if (ItrPhdr.p_type == PT_DYNAMIC) - { - Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)ElfFile + ItrPhdr.p_offset); - for (size_t i = 0; i < ItrPhdr.p_filesz / sizeof(Elf64_Dyn); i++) - { - if (Dynamic[i].d_tag == Tag) - { - debug("Found dynamic tag %d at %#lx [d_val: %#lx].", Tag, &Dynamic[i], Dynamic[i].d_un.d_val); - return &Dynamic[i]; - } - if (Dynamic[i].d_tag == DT_NULL) - { - debug("Reached end of dynamic tag list for tag %d.", Tag); - return nullptr; - } - } - } - } - debug("Dynamic tag %d not found.", Tag); - return nullptr; -#elif defined(a32) - return nullptr; -#endif - } - - MmImage ELFCreateMemoryImage(Memory::MemMgr *mem, Memory::Virtual &pV, void *ElfFile, size_t Length) - { -#if defined(a64) - void *MemoryImage = nullptr; - Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile; - bool IsPIC = ELFHeader->e_type == ET_DYN; - UNUSED(IsPIC); - debug("Elf %s PIC", IsPIC ? "is" : "is not"); - - /* TODO: Not sure what I am supposed to do with this. - * It is supposed to detect if it's PIC or not but I - * don't know if it's right. */ - if (ELFGetDynamicTag(ElfFile, DT_TEXTREL)) - { - fixme("Text relocation is not(?) tested yet!"); - MemoryImage = (uint8_t *)mem->RequestPages(TO_PAGES(Length + 1), true); - memset(MemoryImage, 0, Length); - return {MemoryImage, 0x0}; - } - - Elf64_Phdr ItrPhdr; - uintptr_t FirstProgramHeaderVirtualAddress = 0x0; - - bool FirstProgramHeader = false; - for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) - { - memcpy(&ItrPhdr, - (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, - sizeof(Elf64_Phdr)); - - if (ItrPhdr.p_type == PT_LOAD && !FirstProgramHeader) - { - FirstProgramHeaderVirtualAddress = ItrPhdr.p_vaddr; - FirstProgramHeader = true; - } - - if (ItrPhdr.p_type == PT_LOAD && ItrPhdr.p_vaddr == 0) - { - debug("p_vaddr is 0, allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length); - MemoryImage = mem->RequestPages(TO_PAGES(Length), true); - debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length); - memset(MemoryImage, 0, Length); - return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress}; - } - } - - debug("Allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length); - MemoryImage = mem->RequestPages(TO_PAGES(Length)); - debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length); - memset(MemoryImage, 0, Length); - - if (FirstProgramHeaderVirtualAddress != 0) - FirstProgramHeaderVirtualAddress &= 0xFFFFFFFFFFFFF000; - else - FirstProgramHeaderVirtualAddress = (uintptr_t)MemoryImage; - - for (size_t i = 0; i < TO_PAGES(Length); i++) - { - pV.Remap((void *)((uintptr_t)FirstProgramHeaderVirtualAddress + (i * PAGE_SIZE)), (void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); - debug("Remapped: %#lx -> %#lx", (uintptr_t)FirstProgramHeaderVirtualAddress + (i * PAGE_SIZE), (uintptr_t)MemoryImage + (i * PAGE_SIZE)); - } - return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress}; -#elif defined(a32) - return {}; -#endif - } - - uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, Memory::Virtual &pV, const char *Interpreter) - { - if (GetBinaryType((char *)Interpreter) != BinaryType::BinTypeELF) - { - error("Interpreter \"%s\" is not an ELF file.", Interpreter); - return 0; - } - - /* No need to check if it's valid, the GetBinaryType() call above does that. */ - VirtualFileSystem::File File = vfs->Open(Interpreter); - -#if defined(a64) - Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)File.node->Address; - -#ifdef DEBUG - const char *InterpreterType[6] = { - "ET_NONE", - "ET_REL", - "ET_EXEC", - "ET_DYN", - "ET_CORE", - "ET_LOPROC - ET_HIPROC"}; - Elf64_Half IntType = ELFHeader->e_type; - if (IntType > 5) - IntType = 5; - debug("Interpreter type: %s - %#x", InterpreterType[IntType], ELFHeader->e_type); -#endif - - uintptr_t BaseAddress = UINTPTR_MAX; - uint64_t ElfAppSize = 0; - - Elf64_Phdr ItrPhdr; - - /* Get base address */ - for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) - { - memcpy(&ItrPhdr, - (uint8_t *)File.node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, - sizeof(Elf64_Phdr)); - - BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr); - } - - /* Get size */ - for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) - { - memcpy(&ItrPhdr, - (uint8_t *)File.node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, - sizeof(Elf64_Phdr)); - - uintptr_t SegmentEnd; - SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz; - ElfAppSize = MAX(ElfAppSize, SegmentEnd); - } - - MmImage MemoryImage = ELFCreateMemoryImage(mem, pV, (void *)File.node->Address, ElfAppSize); - - for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++) - { - memcpy(&ItrPhdr, - (uint8_t *)File.node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, - sizeof(Elf64_Phdr)); - - if (ItrPhdr.p_type == PT_LOAD) - { - debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx", - ItrPhdr.p_offset, ItrPhdr.p_vaddr, - ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align); - uintptr_t MAddr = (ItrPhdr.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage.Physical; - fixme("Address: %#lx %s%s%s", MAddr, - (ItrPhdr.p_flags & PF_R) ? "R" : "", - (ItrPhdr.p_flags & PF_W) ? "W" : "", - (ItrPhdr.p_flags & PF_X) ? "X" : ""); - - memcpy((void *)MAddr, (uint8_t *)File.node->Address + ItrPhdr.p_offset, ItrPhdr.p_filesz); - debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)File.node->Address + ItrPhdr.p_offset, MAddr, ItrPhdr.p_filesz); - } - } - - vfs->Close(File); - debug("Interpreter entry point: %#lx (%#lx + %#lx)", (uintptr_t)MemoryImage.Physical + ELFHeader->e_entry, - (uintptr_t)MemoryImage.Physical, ELFHeader->e_entry); - return (uintptr_t)MemoryImage.Physical + ELFHeader->e_entry; -#elif defined(a32) - vfs->Close(File); - return 0; -#endif - } -} diff --git a/Execute/Elf/ParseFunctions/ELFGetDynamicTag.cpp b/Execute/Elf/ParseFunctions/ELFGetDynamicTag.cpp new file mode 100644 index 0000000..f3800b9 --- /dev/null +++ b/Execute/Elf/ParseFunctions/ELFGetDynamicTag.cpp @@ -0,0 +1,62 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include "../../../kernel.h" + +namespace Execute +{ + std::vector ELFGetDynamicTag_x86_64(VirtualFileSystem::File &ElfFile, + DynamicArrayTags Tag) + { + off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); + std::vector Ret; + + Elf64_Ehdr ELFHeader; + vfs->Seek(ElfFile, 0, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + + std::vector DYNAMICPhdrs = ELFGetSymbolType_x86_64(ElfFile, PT_DYNAMIC); + + if (DYNAMICPhdrs.size() < 1) + { + error("No dynamic phdrs found."); + return Ret; + } + + foreach (auto Phdr in DYNAMICPhdrs) + { + Elf64_Dyn Dynamic; + for (size_t i = 0; i < Phdr.p_filesz / sizeof(Elf64_Dyn); i++) + { + vfs->Seek(ElfFile, Phdr.p_offset + (i * sizeof(Elf64_Dyn)), SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&Dynamic, sizeof(Elf64_Dyn)); + + if (Dynamic.d_tag != Tag) + continue; + + debug("Found dynamic tag %d at %#lx [d_val: %#lx].", + Tag, &Dynamic, Dynamic.d_un.d_val); + Ret.push_back(Dynamic); + } + } + + vfs->Seek(ElfFile, OldOffset, SEEK_SET); + return Ret; + } +} diff --git a/Execute/Elf/ParseFunctions/ELFGetSections.cpp b/Execute/Elf/ParseFunctions/ELFGetSections.cpp new file mode 100644 index 0000000..78ab691 --- /dev/null +++ b/Execute/Elf/ParseFunctions/ELFGetSections.cpp @@ -0,0 +1,54 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include "../../../kernel.h" + +namespace Execute +{ + std::vector ELFGetSections_x86_64(VirtualFileSystem::File &ElfFile, + const char *SectionName) + { + off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); + std::vector Ret; + + Elf64_Ehdr ELFHeader; + vfs->Seek(ElfFile, 0, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + + Elf64_Shdr *SectionHeaders = new Elf64_Shdr[ELFHeader.e_shnum]; + vfs->Seek(ElfFile, ELFHeader.e_shoff, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)SectionHeaders, sizeof(Elf64_Shdr) * ELFHeader.e_shnum); + + char *SectionNames = new char[SectionHeaders[ELFHeader.e_shstrndx].sh_size]; + vfs->Seek(ElfFile, SectionHeaders[ELFHeader.e_shstrndx].sh_offset, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)SectionNames, SectionHeaders[ELFHeader.e_shstrndx].sh_size); + + for (Elf64_Half i = 0; i < ELFHeader.e_shnum; ++i) + { + const char *Name = SectionNames + SectionHeaders[i].sh_name; + if (strcmp(Name, SectionName) == 0) + Ret.push_back(SectionHeaders[i]); + } + + vfs->Seek(ElfFile, OldOffset, SEEK_SET); + delete[] SectionHeaders; + delete[] SectionNames; + return Ret; + } +} diff --git a/Execute/Elf/ParseFunctions/ELFGetSymbolType.cpp b/Execute/Elf/ParseFunctions/ELFGetSymbolType.cpp new file mode 100644 index 0000000..85bd4e5 --- /dev/null +++ b/Execute/Elf/ParseFunctions/ELFGetSymbolType.cpp @@ -0,0 +1,50 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include "../../../kernel.h" + +namespace Execute +{ + std::vector ELFGetSymbolType_x86_64(VirtualFileSystem::File &ElfFile, + SegmentTypes Tag) + { + off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); + std::vector Ret; + + Elf64_Ehdr ELFHeader; + vfs->Seek(ElfFile, 0, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + + Elf64_Phdr ProgramHeaders; + vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET); + vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); + + for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) + { + if (ProgramHeaders.p_type == Tag) + Ret.push_back(ProgramHeaders); + + vfs->Seek(ElfFile, sizeof(Elf64_Phdr), SEEK_CUR); + vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); + } + + vfs->Seek(ElfFile, OldOffset, SEEK_SET); + return Ret; + } +} diff --git a/Execute/Elf/SharedObjects.cpp b/Execute/Elf/SharedObjects.cpp deleted file mode 100644 index 0da1967..0000000 --- a/Execute/Elf/SharedObjects.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include -#include -#include - -#ifdef DEBUG -#include -#endif - -#include "../../kernel.h" -#include "../../Fex.hpp" - -using namespace Tasking; - -NewLock(ExecuteServiceLock); - -namespace Execute -{ - Memory::MemMgr *mem = nullptr; - std::vector Libs; - - void StartExecuteService() - { - mem = new Memory::MemMgr; - - while (true) - { - { - SmartLock(ExecuteServiceLock); - foreach (auto &Lib in Libs) - { - if (Lib.RefCount > 0) - { - Lib.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes); - debug("Reset timeout for %s", Lib.Identifier); - continue; - } - if (Lib.Timeout < TimeManager->GetCounter()) - { - // TODO: Remove - fixme("Removed library %s because of timeout", Lib.Identifier); - } - else - { - debug("Timeout for %s is %ld", Lib.Identifier, Lib.Timeout); - } - } - debug("Waiting 10 seconds..."); - } - TaskManager->Sleep(10000); - } - } - - bool AddLibrary(char *Identifier, void *ElfImage, size_t Length, const Memory::Virtual &pV) - { - SmartLock(ExecuteServiceLock); - SharedLibraries sl; - - foreach (auto lib in Libs) - { - if (strcmp(lib.Identifier, Identifier) == 0) - { - debug("Library %s already loaded", Identifier); - lib.RefCount++; - return true; - } - } - - strcpy(sl.Identifier, Identifier); - sl.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes); - sl.RefCount = 0; - - void *LibFile = mem->RequestPages(TO_PAGES(Length + 1), true); - debug("LibFile: %#lx", LibFile); - memcpy(LibFile, (void *)ElfImage, Length); - Memory::Virtual().Map(LibFile, LibFile, Length, Memory::RW | Memory::US | Memory::G); - - Memory::Virtual ncpV = pV; - sl.MemoryImage = r_cst(uint64_t, ELFCreateMemoryImage(mem, ncpV, LibFile, Length).Physical); - debug("MemoryImage: %#lx", sl.MemoryImage); - - uintptr_t BaseAddress = UINTPTR_MAX; - { -#if defined(a64) - Elf64_Phdr ItrProgramHeader; - - for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_phnum; i++) - { - memcpy(&ItrProgramHeader, (uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_phoff + ((Elf64_Ehdr *)LibFile)->e_phentsize * i, sizeof(Elf64_Phdr)); - BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr); - } - - for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_phnum; i++) - { - memcpy(&ItrProgramHeader, (uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_phoff + ((Elf64_Ehdr *)LibFile)->e_phentsize * i, sizeof(Elf64_Phdr)); - if (ItrProgramHeader.p_type != PT_LOAD) - continue; - - debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx", - ItrProgramHeader.p_offset, ItrProgramHeader.p_vaddr, - ItrProgramHeader.p_filesz, ItrProgramHeader.p_memsz, ItrProgramHeader.p_align); - uintptr_t MAddr = (ItrProgramHeader.p_vaddr - BaseAddress) + (uintptr_t)sl.MemoryImage; - fixme("Address: %#lx %s%s%s", MAddr, - (ItrProgramHeader.p_flags & PF_R) ? "R" : "", - (ItrProgramHeader.p_flags & PF_W) ? "W" : "", - (ItrProgramHeader.p_flags & PF_X) ? "X" : ""); - - memcpy((void *)MAddr, (uint8_t *)LibFile + ItrProgramHeader.p_offset, ItrProgramHeader.p_filesz); - debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)LibFile + ItrProgramHeader.p_offset, (uintptr_t)MAddr, ItrProgramHeader.p_filesz); - break; -#elif defined(a32) -#endif - } - -#if defined(a64) - struct Elf64_Dyn *JmpRel = ELFGetDynamicTag((void *)LibFile, DT_JMPREL); - struct Elf64_Dyn *SymTab = ELFGetDynamicTag((void *)LibFile, DT_SYMTAB); - struct Elf64_Dyn *StrTab = ELFGetDynamicTag((void *)LibFile, DT_STRTAB); - - if (!JmpRel) - { - debug("No DT_JMPREL"); - } - - if (!SymTab) - { - debug("No DT_SYMTAB"); - } - - if (!StrTab) - { - debug("No DT_STRTAB"); - } - - if (JmpRel && SymTab && StrTab) - { - debug("JmpRel: %#lx, SymTab: %#lx, StrTab: %#lx", JmpRel->d_un.d_ptr, SymTab->d_un.d_ptr, StrTab->d_un.d_ptr); - Elf64_Rela *_JmpRel = (Elf64_Rela *)(sl.MemoryImage + (JmpRel->d_un.d_ptr - BaseAddress)); - Elf64_Sym *_SymTab = (Elf64_Sym *)(sl.MemoryImage + (SymTab->d_un.d_ptr - BaseAddress)); - - char *_DynStr = (char *)(sl.MemoryImage + (StrTab->d_un.d_ptr - BaseAddress)); - - Elf64_Shdr *gotSection = nullptr; - for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_shnum; i++) - { - Elf64_Shdr *shdr = (Elf64_Shdr *)((uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_shoff + i * sizeof(Elf64_Shdr)); - if (shdr->sh_type == SHT_PROGBITS && (shdr->sh_flags & SHF_WRITE) && (shdr->sh_flags & SHF_ALLOC)) - { - gotSection = shdr; - break; - } - } - - debug("LIB_DBG"); - - if (gotSection) - { - Elf64_Xword numEntries = gotSection->sh_size / sizeof(Elf64_Addr); - for (Elf64_Xword i = 0; i < numEntries - 3; i++) - { - Elf64_Rela *Rel = _JmpRel + i; - Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset + sl.MemoryImage); - - Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info); - debug("r_offset: %#lx RelType: %d", Rel->r_offset, RelType); - - switch (RelType) - { - case R_X86_64_NONE: - break; - case R_X86_64_JUMP_SLOT: - { - Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info); - Elf64_Sym *Sym = _SymTab + SymIndex; - - if (Sym->st_name) - { - char *SymName = _DynStr + Sym->st_name; - debug("SymName: %s", SymName); - - Elf64_Sym *LibSym = ELFLookupSymbol((Elf64_Ehdr *)LibFile, SymName); - - if (LibSym) - { - *GOTEntry = (Elf64_Addr)(sl.MemoryImage + LibSym->st_value); - debug("GOT[%ld]: %#lx + %#lx = %#lx", i, sl.MemoryImage, LibSym->st_value, *GOTEntry); - } - } - break; - } - default: - { - fixme("RelType %d not supported", RelType); - break; - } - } - - debug("GOT[%ld](%#lx): %#lx", i, GOTEntry, *GOTEntry); - } - } - else - { - debug("GOT section not found"); - } - } - } - - sl.Address = r_cst(uint64_t, LibFile); - debug("Casted LibFile %#lx -> %#lx", LibFile, sl.Address); - sl.Length = Length; - - debug("Library %s loaded at %#lx (full file: %#lx)", Identifier, sl.MemoryImage, LibFile); - - Libs.push_back(sl); - return true; -#elif defined(a32) - return false; -#endif - } - - void SearchLibrary(char *Identifier) - { - UNUSED(Identifier); - SmartLock(ExecuteServiceLock); - } - - SharedLibraries GetLibrary(char *Identifier) - { - SmartLock(ExecuteServiceLock); - foreach (auto Lib in Libs) - { - if (strcmp(Lib.Identifier, Identifier) == 0) - { - Lib.RefCount++; - debug("Library %s found (%#lx %#lx)", Identifier, Lib.Address, Lib.MemoryImage); - return Lib; - } - } - // throw std::runtime_error("Library not found"); - return SharedLibraries(); - } -} diff --git a/Execute/Parse.cpp b/Execute/Parse.cpp deleted file mode 100644 index 00a126d..0000000 --- a/Execute/Parse.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include - -#include "../kernel.h" -#include "../Fex.hpp" - -namespace Execute -{ - BinaryType GetBinaryType(void *Image) - { - Fex *FexHdr = (Fex *)Image; - - /* Elf64_Ehdr and Elf32_Ehdr are very similar (Elf64_Half and - Elf32_Half are the same size type) so we can use directly Elf64_Ehdr. */ - Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)Image; - - IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Image; - - /* Check Fex magic */ - if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0') - { - /* If the fex type is driver, we shouldn't return as Fex. */ - if (FexHdr->Type == FexFormatType::FexFormatType_Executable) - { - debug("Image - Fex"); - return BinaryType::BinTypeFex; - } - else if (FexHdr->Type == FexFormatType::FexFormatType_Driver) - { - debug("Fex Driver is not supposed to be executed."); - } - } - /* Check ELF magic. */ - else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 && - ELFHeader->e_ident[EI_MAG1] == ELFMAG1 && - ELFHeader->e_ident[EI_MAG2] == ELFMAG2 && - ELFHeader->e_ident[EI_MAG3] == ELFMAG3) - { - debug("Image - ELF"); - return BinaryType::BinTypeELF; - } - /* Every Windows executable starts with MZ header. */ - else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE) - { - IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Image) + MZHeader->e_lfanew); - IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Image) + MZHeader->e_lfanew); - - /* TODO: LE, EDOS */ - if (PEHeader->Signature == IMAGE_NT_SIGNATURE) - { - debug("Image - PE"); - return BinaryType::BinTypePE; - } - else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE) - { - debug("Image - NE"); - return BinaryType::BinTypeNE; - } - else - { - debug("Image - MZ"); - return BinaryType::BinTypeMZ; - } - } - - /* ... */ - return BinaryType::BinTypeUnknown; - } - - BinaryType GetBinaryType(char *Path) - { - BinaryType Type = BinaryType::BinTypeInvalid; - VirtualFileSystem::File ExFile = vfs->Open(Path); - - if (ExFile.IsOK()) - { - debug("File opened: %s", Path); - Type = GetBinaryType((void *)ExFile.node->Address); - } - - vfs->Close(ExFile); - return Type; - } -} diff --git a/Execute/Spawn.cpp b/Execute/Spawn.cpp index fcd5617..e33fa14 100644 --- a/Execute/Spawn.cpp +++ b/Execute/Spawn.cpp @@ -31,79 +31,69 @@ using namespace Tasking; namespace Execute { - SpawnData Spawn(char *Path, const char **argv, const char **envp) - { - SpawnData ret = {.Status = ExStatus::Unknown, - .Process = nullptr, - .Thread = nullptr}; + SpawnData Spawn(char *Path, const char **argv, const char **envp) + { + SpawnData ret = {.Status = ExStatus::Unknown, + .Process = nullptr, + .Thread = nullptr}; - VirtualFileSystem::File ExFile = vfs->Open(Path); + VirtualFileSystem::File ExFile = vfs->Open(Path); - if (ExFile.IsOK()) - { - if (ExFile.node->Flags != VirtualFileSystem::NodeFlags::FILE) - { - ret.Status = ExStatus::InvalidFilePath; - goto Exit; - } + if (!ExFile.IsOK()) + { + if (ExFile.Status == VirtualFileSystem::FileStatus::NotFound) + { + ret.Status = ExStatus::InvalidFilePath; + goto Exit; + } + else + { + ret.Status = ExStatus::InvalidFile; + goto Exit; + } - switch (GetBinaryType(Path)) - { - case BinaryType::BinTypeFex: - { - Fex *FexHdr = (Fex *)ExFile.node->Address; - if (FexHdr->Type == FexFormatType::FexFormatType_Executable) - { - const char *BaseName; - cwk_path_get_basename(Path, &BaseName, nullptr); - PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User); + if (ExFile.GetFlags() != VirtualFileSystem::NodeFlags::FILE) + { + ret.Status = ExStatus::InvalidFilePath; + goto Exit; + } + } - void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile.node->Length + 1)); - memcpy(BaseImage, (void *)ExFile.node->Address, ExFile.node->Length); + switch (GetBinaryType(Path)) + { + case BinaryType::BinTypeFex: + { + Fex FexHdr; + vfs->Read(ExFile, (uint8_t *)&FexHdr, sizeof(Fex)); + if (FexHdr.Type == FexFormatType::FexFormatType_Executable) + { + stub; + assert(false); + } - Memory::Virtual(Process->PageTable).Map((void *)BaseImage, (void *)BaseImage, ExFile.node->Length, Memory::PTFlag::RW | Memory::PTFlag::US); + ret.Status = ExStatus::InvalidFileHeader; + break; + } + case BinaryType::BinTypeELF: + { + ELFBaseLoad bl = ELFLoad(Path, argv, envp); + if (!bl.Success) + { + ret.Status = ExStatus::LoadingProcedureFailed; + break; + } + ret = bl.sd; + break; + } + default: + { + ret.Status = ExStatus::Unsupported; + break; + } + } - std::vector auxv; // TODO! - - TCB *Thread = TaskManager->CreateThread(Process, - (IP)FexHdr->EntryPoint, - argv, envp, auxv, - (IPOffset)BaseImage, - TaskArchitecture::x64, - TaskCompatibility::Native); - ret.Process = Process; - ret.Thread = Thread; - ret.Status = ExStatus::OK; - } - - ret.Status = ExStatus::InvalidFileHeader; - goto Exit; - } - case BinaryType::BinTypeELF: - { - ELFBaseLoad bl = ELFLoad(Path, argv, envp); - if (!bl.Success) - { - ret.Status = ExStatus::GenericError; - goto Exit; - } - ret = bl.sd; - goto Exit; - } - default: - { - ret.Status = ExStatus::Unsupported; - goto Exit; - } - } - } - else if (ExFile.Status == VirtualFileSystem::FileStatus::NotFound) - ret.Status = ExStatus::InvalidFilePath; - else - ret.Status = ExStatus::InvalidFile; - - Exit: - vfs->Close(ExFile); - return ret; - } + Exit: + vfs->Close(ExFile); + return ret; + } } diff --git a/FileSystem/FS/ustar.cpp b/FileSystem/FS/ustar.cpp index f79654b..3292c1c 100644 --- a/FileSystem/FS/ustar.cpp +++ b/FileSystem/FS/ustar.cpp @@ -28,52 +28,20 @@ namespace VirtualFileSystem { if (!Size) Size = node->Length; - if (Offset > node->Length) + + if ((size_t)node->Offset > node->Length) return 0; - if (Offset + Size > node->Length) - Size = node->Length - Offset; - memcpy(Buffer, (uint8_t *)(node->Address + Offset), Size); + + if (node->Offset + Size > node->Length) + Size = node->Length - node->Offset; + + memcpy(Buffer, (uint8_t *)(node->Address + node->Offset), Size); return Size; } - SeekFSFunction(USTAR_Seek) - { - long NewOffset; - - if (Whence == SEEK_SET) - { - if (Offset > node->Length) - return -1; - node->Offset = Offset; - NewOffset = node->Offset; - } - else if (Whence == SEEK_CUR) - { - NewOffset = node->Offset + Offset; - if ((size_t)NewOffset > node->Length || NewOffset < 0) - return -1; - node->Offset = NewOffset; - } - else if (Whence == SEEK_END) - { - NewOffset = node->Length + Offset; - if (NewOffset < 0) - return -1; - node->Offset = NewOffset; - } - else - { - error("Invalid whence!"); - return -1; - } - - return NewOffset; - } - FileSystemOperations ustar_op = { .Name = "ustar", .Read = USTAR_Read, - .Seek = USTAR_Seek, }; bool USTAR::TestArchive(uintptr_t Address) diff --git a/FileSystem/Filesystem.cpp b/FileSystem/Filesystem.cpp index 4273832..9da7152 100644 --- a/FileSystem/Filesystem.cpp +++ b/FileSystem/Filesystem.cpp @@ -46,7 +46,6 @@ namespace VirtualFileSystem size_t Size = 1; size_t PathSize = 0; - // Traverse the filesystem tree and build the path by adding each parent's Name field to the Path array while (Parent != FileSystemRoot && Parent != nullptr) { bool Found = false; @@ -82,36 +81,26 @@ namespace VirtualFileSystem Parent = Parent->Parent; } - // Calculate the total size of the final path string for (size_t i = 0; i < PathSize; i++) - { Size += strlen(Path[i]); - } - // Allocate a new string for the final path std::shared_ptr FinalPath; FinalPath.reset(new char[Size]); size_t Offset = 0; - // Concatenate the elements of the Path array into the FinalPath string for (size_t i = PathSize - 1; i < PathSize; i--) { if (Path[i] == nullptr) - { continue; - } + size_t ElementSize = strlen(Path[i]); memcpy(FinalPath.get() + Offset, Path[i], ElementSize); Offset += ElementSize; } - // Add a null terminator to the final path string FinalPath.get()[Size - 1] = '\0'; - - // Deallocate the Path array delete[] Path, Path = nullptr; - vfsdbg("GetPathFromNode()->\"%s\"", FinalPath.get()); return FinalPath; } @@ -498,7 +487,7 @@ namespace VirtualFileSystem return FileStatus::OK; } - size_t Virtual::Read(File &File, size_t Offset, uint8_t *Buffer, size_t Size) + size_t Virtual::Read(File &File, uint8_t *Buffer, size_t Size) { SmartLock(VFSLock); if (unlikely(!File.node)) @@ -516,10 +505,10 @@ namespace VirtualFileSystem File.Status = FileStatus::OK; vfsdbg("Reading %s out->%016x", File.Name, Buffer); - return File.node->Operator->Read(File.node, Offset, Size, Buffer); + return File.node->Operator->Read(File.node, Size, Buffer); } - size_t Virtual::Write(File &File, size_t Offset, uint8_t *Buffer, size_t Size) + size_t Virtual::Write(File &File, uint8_t *Buffer, size_t Size) { SmartLock(VFSLock); if (unlikely(!File.node)) @@ -537,7 +526,72 @@ namespace VirtualFileSystem File.Status = FileStatus::OK; vfsdbg("Writing %s out->%016x", File.Name, Buffer); - return File.node->Operator->Write(File.node, Offset, Size, Buffer); + return File.node->Operator->Write(File.node, Size, Buffer); + } + + off_t Virtual::Seek(File &File, off_t Offset, uint8_t Whence) + { + SmartLock(VFSLock); + Node *node = File.node; + File.Status = FileStatus::OK; + + if (unlikely(!node)) + { + File.Status = FileStatus::InvalidNode; + return -1; + } + + if (unlikely(!node->Operator)) + { + File.Status = FileStatus::InvalidOperator; + return -1; + } + + if (unlikely(node->Operator->Seek)) + { + node->Offset = File.ContextOffset; + File.ContextOffset = node->Operator->Seek(node, Offset, Whence); + return File.ContextOffset; + } + + switch (Whence) + { + case SEEK_SET: + { + if ((size_t)Offset > node->Length) + return -1; + + File.ContextOffset = node->Offset = Offset; + break; + } + case SEEK_CUR: + { + off_t NewOffset = File.ContextOffset + Offset; + if ((size_t)NewOffset > node->Length || + NewOffset < 0) + return -1; + + File.ContextOffset = node->Offset = NewOffset; + break; + } + case SEEK_END: + { + off_t NewOffset = node->Length + Offset; + if ((size_t)NewOffset > node->Length || + NewOffset < 0) + return -1; + + File.ContextOffset = node->Offset = NewOffset; + break; + } + default: + { + error("Invalid whence!"); + return -1; + } + } + + return File.ContextOffset; } /* TODO: CHECK Open */ @@ -551,6 +605,7 @@ namespace VirtualFileSystem { File file{}; file.node = FileSystemRoot; + strcpy(file.Name, "/"); return file; } @@ -559,8 +614,10 @@ namespace VirtualFileSystem { File file{}; file.node = Parent; + if (unlikely(!file.node)) file.Status = FileStatus::NotFound; + cwk_path_get_basename(GetPathFromNode(Parent).get(), &basename, nullptr); strcpy(file.Name, basename); return file; @@ -575,6 +632,7 @@ namespace VirtualFileSystem if (!file.node) file.Status = FileStatus::NotFound; + cwk_path_get_basename(GetPathFromNode(Parent).get(), &basename, nullptr); strcpy(file.Name, basename); return file; @@ -631,6 +689,8 @@ namespace VirtualFileSystem if (unlikely(!File.node)) return FileStatus::InvalidHandle; vfsdbg("Closing %s", File.Name); + + File.node->Offset = 0; return FileStatus::OK; } diff --git a/Kernel.cpp b/Kernel.cpp index 7a5fc3c..77de90e 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -77,6 +77,8 @@ LockClass mExtTrkLock; * - [ ] COW (Copy On Write) for the virtual memory. (https://en.wikipedia.org/wiki/Copy-on-write) * - [ ] Bootstrap should have a separate bss section + PHDR. * - [ ] Reimplement the driver conflict detection. + * - [ ] Elf loader shouldn't create a full copy of the elf binary. Copy only the needed sections. + * - [ ] Use NX-bit. * * ISSUES: * - [x] Kernel stack is smashed when an interrupt occurs. (this bug it occurs when an interrupt like IRQ1 or IRQ12 occurs) @@ -168,6 +170,19 @@ LockClass mExtTrkLock; * - Atomic operations: * https://en.cppreference.com/w/cpp/atomic/atomic * + * - ELF: + * https://www.sco.com/developers/gabi/latest/ch4.eheader.html + * https://refspecs.linuxfoundation.org/elf/elf.pdf + * https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-42444/index.html + * https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-83432/index.html + * https://www.youtube.com/watch?v=nC1U1LJQL8o + * https://stevens.netmeister.org/631/elf.html + * https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h + * + * - C++ ABI: + * https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3 + * https://itanium-cxx-abi.github.io/cxx-abi/abi.html + * */ #ifdef a64 @@ -259,8 +274,12 @@ EXTERNC void KPrint(const char *Format, ...) EXTERNC NIF void Main() { Display = new Video::Display(bInfo.Framebuffer[0]); - KPrint("%s - %s [\e058C19%s\eFFFFFF]", KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT); - KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s", CPU::Hypervisor(), CPU::Vendor(), CPU::Name()); + + KPrint("%s - %s [\e058C19%s\eFFFFFF]", + KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT); + KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s", + CPU::Hypervisor(), CPU::Vendor(), CPU::Name()); + if (DebuggerIsAttached) KPrint("\eFFA500Kernel debugger detected."); @@ -293,7 +312,8 @@ EXTERNC NIF void Main() Video::FontInfo fi = Display->GetCurrentFont()->GetInfo(); Display->SetBufferCursor(1, 0, buf->Height - fi.Height); PutCharBufferIndex = 1; - printf("Fennix Operating System - %s [\e058C19%s\eFFFFFF]\n", KERNEL_VERSION, GIT_COMMIT_SHORT); + printf("Fennix Operating System - %s [\e058C19%s\eFFFFFF]\n", + KERNEL_VERSION, GIT_COMMIT_SHORT); Display->SetBuffer(1); PutCharBufferIndex = 0; } @@ -434,13 +454,13 @@ EXTERNC NIF void Main() else { File dev = vfs->Open("/dev"); - if (dev.node->Flags != NodeFlags::DIRECTORY) + if (dev.GetFlags() != NodeFlags::DIRECTORY) { KPrint("\eE85230/dev is not a directory! Halting..."); CPU::Stop(); } vfs->Close(dev); - DevFS = dev.node; + DevFS = dev.GetNode(); } if (!vfs->PathExists("/mnt")) @@ -448,13 +468,13 @@ EXTERNC NIF void Main() else { File mnt = vfs->Open("/mnt"); - if (mnt.node->Flags != NodeFlags::DIRECTORY) + if (mnt.GetFlags() != NodeFlags::DIRECTORY) { KPrint("\eE85230/mnt is not a directory! Halting..."); CPU::Stop(); } vfs->Close(mnt); - MntFS = mnt.node; + MntFS = mnt.GetNode(); } if (!vfs->PathExists("/proc")) @@ -462,13 +482,41 @@ EXTERNC NIF void Main() else { File proc = vfs->Open("/proc", nullptr); - if (proc.node->Flags != NodeFlags::DIRECTORY) + if (proc.GetFlags() != NodeFlags::DIRECTORY) { KPrint("\eE85230/proc is not a directory! Halting..."); CPU::Stop(); } vfs->Close(proc); - ProcFS = proc.node; + ProcFS = proc.GetNode(); + } + + if (!vfs->PathExists("/var")) + VarLogFS = vfs->Create("/var", NodeFlags::DIRECTORY); + else + { + File var = vfs->Open("/var", nullptr); + if (var.GetFlags() != NodeFlags::DIRECTORY) + { + KPrint("\eE85230/var is not a directory! Halting..."); + CPU::Stop(); + } + vfs->Close(var); + VarLogFS = var.GetNode(); + + if (!vfs->PathExists("/var/log")) + VarLogFS = vfs->Create("/var/log", NodeFlags::DIRECTORY); + else + { + File var_log = vfs->Open("/var/log", nullptr); + if (var_log.GetFlags() != NodeFlags::DIRECTORY) + { + KPrint("\eE85230/var/log is not a directory! Halting..."); + CPU::Stop(); + } + vfs->Close(var_log); + VarLogFS = var_log.GetNode(); + } } KPrint("\e058C19################################"); @@ -552,7 +600,7 @@ EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot) if (DriverManager) delete DriverManager, DriverManager = nullptr; - if (TaskManager) + if (TaskManager && !TaskManager->IsPanic()) { TaskManager->SignalShutdown(); delete TaskManager, TaskManager = nullptr; diff --git a/KernelThread.cpp b/KernelThread.cpp index 888342e..66084c5 100644 --- a/KernelThread.cpp +++ b/KernelThread.cpp @@ -51,6 +51,7 @@ Recovery::KernelRecovery *RecoveryScreen = nullptr; VirtualFileSystem::Node *DevFS = nullptr; VirtualFileSystem::Node *MntFS = nullptr; VirtualFileSystem::Node *ProcFS = nullptr; +VirtualFileSystem::Node *VarLogFS = nullptr; NewLock(ShutdownLock); @@ -226,27 +227,26 @@ void TestSyscallsKernel() nullptr, nullptr, std::vector(), - 0, Tasking::TaskArchitecture::x64, Tasking::TaskCompatibility::Native, true); SyscallsTestThread->SetCritical(true); TaskManager->GetSecurityManager()->TrustToken(SyscallsTestThread->Security.UniqueToken, Tasking::TTL::FullTrust); - Memory::Virtual va = Memory::Virtual(SyscallsTestProcess->PageTable); + Memory::Virtual vmm = Memory::Virtual(SyscallsTestProcess->PageTable); - // va.Remap((void *)TestSyscalls, va.GetPhysical((void *)TestSyscalls), Memory::P | Memory::RW | Memory::US); + // vmm.Remap((void *)TestSyscalls, vmm.GetPhysical((void *)TestSyscalls), Memory::P | Memory::RW | Memory::US); // for (uintptr_t k = (uintptr_t)&_kernel_start; k < (uintptr_t)&_kernel_end; k += PAGE_SIZE) // { - // va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US); - // debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k)); + // vmm.Remap((void *)k, (void *)vmm.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US); + // debug("Remapped %#lx %#lx", k, vmm.GetPhysical((void *)k)); // } for (uintptr_t k = (uintptr_t)TestSyscalls - PAGE_SIZE; k < (uintptr_t)TestSyscalls + FROM_PAGES(5); k += PAGE_SIZE) { - va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US); - debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k)); + vmm.Remap((void *)k, (void *)vmm.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US); + debug("Remapped %#lx %#lx", k, vmm.GetPhysical((void *)k)); } SyscallsTestThread->Status = Tasking::TaskStatus::Ready; @@ -274,7 +274,7 @@ Execute::SpawnData SpawnInit() } /* Files: 0.tga 1.tga ... 26.tga */ -void *Frames[27]; +uint8_t *Frames[27]; uint32_t FrameSizes[27]; size_t FrameCount = 1; @@ -292,9 +292,9 @@ void BootLogoAnimationThread() break; } - FrameSizes[FrameCount] = s_cst(uint32_t, ba.node->Length); - Frames[FrameCount] = new uint8_t[ba.node->Length]; - memcpy((void *)Frames[FrameCount], (void *)ba.node->Address, ba.node->Length); + FrameSizes[FrameCount] = s_cst(uint32_t, ba.GetLength()); + Frames[FrameCount] = new uint8_t[ba.GetLength()]; + vfs->Read(ba, Frames[FrameCount], ba.GetLength()); vfs->Close(ba); FrameCount++; } @@ -425,7 +425,7 @@ void KernelMainThread() } #ifdef DEBUG - Tasking::TCB *tskMgr = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr); + TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr); TreeFS(vfs->GetRootNode(), 0); TestSyscallsKernel(); #endif @@ -462,7 +462,7 @@ void KernelMainThread() Execute::SpawnData ret = {Execute::ExStatus::Unknown, nullptr, nullptr}; Tasking::TCB *ExecuteThread = nullptr; int ExitCode = -1; - ExecuteThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)Execute::StartExecuteService); + ExecuteThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)Execute::LibraryManagerService); ExecuteThread->Rename("Library Manager"); ExecuteThread->SetCritical(true); ExecuteThread->SetPriority(Tasking::Idle); @@ -499,7 +499,8 @@ void KernelMainThread() Exit: if (ExitCode != 0) { - KPrint("\eE85230Userspace process exited with code %d", ExitCode); + KPrint("\eE85230Userspace process exited with code %d (%#x)", ExitCode, + ExitCode < 0 ? ExitCode * -1 : ExitCode); KPrint("Dropping to recovery screen..."); TaskManager->Sleep(2500); TaskManager->WaitForThread(blaThread); diff --git a/Library/cxxabi.cpp b/Library/cxxabi.cpp deleted file mode 100644 index fc06100..0000000 --- a/Library/cxxabi.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include - -// TODO: complete implementation for everything -// TODO: https://wiki.osdev.org/C%2B%2B - -#define ATEXIT_MAX_FUNCS 128 - -typedef unsigned uarch_t; - -struct atexit_func_entry_t -{ - /* - * Each member is at least 4 bytes large. Such that each entry is 12bytes. - * 128 * 12 = 1.5KB exact. - **/ - void (*destructor_func)(void *); - void *obj_ptr; - void *dso_handle; -}; - -typedef enum -{ - _URC_NO_REASON = 0, - _URC_FOREIGN_EXCEPTION_CAUGHT = 1, - _URC_FATAL_PHASE2_ERROR = 2, - _URC_FATAL_PHASE1_ERROR = 3, - _URC_NORMAL_STOP = 4, - _URC_END_OF_STACK = 5, - _URC_HANDLER_FOUND = 6, - _URC_INSTALL_CONTEXT = 7, - _URC_CONTINUE_UNWIND = 8 -} _Unwind_Reason_Code; - -struct _Unwind_Context; -typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); -typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__))); -typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__))); -typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code, struct _Unwind_Exception *); -typedef int _Unwind_Action; - -struct type_info -{ - const char *name; -}; - -struct unexpected_handler -{ - void (*unexpected)(); -}; - -struct terminate_handler -{ - void (*handler)(); -}; - -struct _Unwind_Exception -{ - _Unwind_Exception_Class exception_class; - _Unwind_Exception_Cleanup_Fn exception_cleanup; -#if !defined(__USING_SJLJ_EXCEPTIONS__) && defined(__SEH__) - _Unwind_Word private_[6]; -#else - _Unwind_Word private_1; - _Unwind_Word private_2; -#endif -} __attribute__((__aligned__)); - -struct __cxa_exception -{ -#if __LP64__ - size_t referenceCount; -#endif - type_info *exceptionType; - void (*exceptionDestructor)(void *); - unexpected_handler unexpectedHandler; - terminate_handler terminateHandler; - __cxa_exception *nextException; - int handlerCount; - -#ifdef __ARM_EABI_UNWINDER__ - __cxa_exception *nextPropagatingException; - int propagationCount; -#else - int handlerSwitchValue; - const unsigned char *actionRecord; - const unsigned char *languageSpecificData; - _Unwind_Ptr catchTemp; - void *adjustedPtr; -#endif -#if !__LP64__ - size_t referenceCount; -#endif - _Unwind_Exception unwindHeader; -}; - -/* extern */ void *__dso_handle = 0; -atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS]; -uarch_t __atexit_func_count = 0; - -extern "C" int __cxa_atexit(void (*f)(void *), void *objptr, void *dso) -{ - fixme("__cxa_atexit( %p %p %p ) triggered.", f, objptr, dso); - if (__atexit_func_count >= ATEXIT_MAX_FUNCS) - return -1; - __atexit_funcs[__atexit_func_count].destructor_func = f; - __atexit_funcs[__atexit_func_count].obj_ptr = objptr; - __atexit_funcs[__atexit_func_count].dso_handle = dso; - __atexit_func_count++; - return 0; -} - -extern "C" void __cxa_finalize(void *f) -{ - fixme("__cxa_finalize( %p ) triggered.", f); - uarch_t i = __atexit_func_count; - if (!f) - { - while (i--) - if (__atexit_funcs[i].destructor_func) - (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); - - return; - } - - while (i--) - if (__atexit_funcs[i].destructor_func == f) - { - (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); - __atexit_funcs[i].destructor_func = 0; - } -} - -extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, _Unwind_Exception *ue_header, _Unwind_Context *context) -{ - fixme("__gxx_personality_v0( %d %p %p %p %p ) triggered.", version, actions, exception_class, ue_header, context); - return _URC_NO_REASON; -} - -extern "C" void _Unwind_Resume(struct _Unwind_Exception *exc) { fixme("_Unwind_Resume( %p ) triggered.", exc); } - -static inline size_t align_exception_allocation_size(size_t s, size_t a) { return (s + a - 1) & ~(a - 1); } - -void unexpected_header_stub() { fixme("unexpected() called."); } -void terminate_header_stub() { fixme("terminate() called."); } - -extern "C" void *__cxa_allocate_exception(size_t thrown_size) throw() -{ - fixme("__cxa_allocate_exception( %d ) triggered.", thrown_size); - - size_t real_size = align_exception_allocation_size(thrown_size + sizeof(__cxa_exception), alignof(__cxa_exception)); - - __cxa_exception *header = (__cxa_exception *)kmalloc(real_size); - if (!header) - { - error("Failed to allocate exception."); - return nullptr; - } - - header->referenceCount = 1; - header->exceptionType = nullptr; - header->exceptionDestructor = nullptr; - header->unexpectedHandler = {.unexpected = unexpected_header_stub}; - header->terminateHandler = {.handler = terminate_header_stub}; - header->nextException = nullptr; - header->handlerCount = -1; - header->handlerSwitchValue = 0; - header->actionRecord = nullptr; - header->languageSpecificData = nullptr; - header->catchTemp = 0; - header->adjustedPtr = nullptr; - - return header + 1; -} - -extern "C" void _Unwind_RaiseException(_Unwind_Exception *exc) -{ - fixme("_Unwind_RaiseException( %p ) triggered.", exc); - - __cxa_exception *header = ((__cxa_exception *)exc) - 1; - if (header->terminateHandler.handler) - { - debug("Calling terminate handler."); - header->terminateHandler.handler(); - } - else - { - error("Unhandled exception."); - CPU::Stop(); - } - - CPU::Halt(true); -} - -extern "C" void __cxa_throw(void *thrown_object, void *tinfo, void (*dest)(void *)) -{ - fixme("__cxa_throw( %p %p %p ) triggered.", thrown_object, tinfo, dest); - - __cxa_exception *header = ((__cxa_exception *)thrown_object) - 1; - header->exceptionType = (type_info *)tinfo; - header->exceptionDestructor = dest; - - _Unwind_RaiseException(&header->unwindHeader); -} - -extern "C" void __cxa_rethrow() { fixme("__cxa_rethrow() triggered."); } - -extern "C" void __cxa_pure_virtual() { fixme("__cxa_pure_virtual() triggered."); } - -extern "C" void __cxa_throw_bad_array_new_length() { fixme("__cxa_throw_bad_array_new_length() triggered."); } - -extern "C" void __cxa_free_exception(void *thrown_exception) { fixme("__cxa_free_exception( %p ) triggered.", thrown_exception); } - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) -extern "C" void *__cxa_begin_catch(void *e) throw() -#else -extern "C" void *__cxa_begin_catch(void *e) -#endif -{ - fixme("__cxa_begin_catch( %p ) triggered.", e); - return (void *)0; -} - -extern "C" void __cxa_end_catch() { fixme("__cxa_end_catch() triggered."); } - -__extension__ typedef int __guard __attribute__((mode(__DI__))); - -extern "C" int __cxa_guard_acquire(__guard *g) -{ - fixme("__cxa_guard_acquire( %p ) triggered.", g); - return !*(char *)(g); -} - -extern "C" void __cxa_guard_release(__guard *g) -{ - fixme("__cxa_guard_release( %p ) triggered.", g); - *(char *)g = 1; -} - -extern "C" void __cxa_guard_abort(__guard *g) { fixme("__cxa_guard_abort( %p ) triggered.", g); } - -// vtable for __cxxabiv1::__class_type_info -extern "C" void *_ZTVN10__cxxabiv117__class_type_infoE(void) -{ - fixme("_ZTVN10__cxxabiv117__class_type_infoE() triggered."); - return (void *)0; -} - -// vtable for __cxxabiv1::__si_class_type_info -extern "C" void *_ZTVN10__cxxabiv120__si_class_type_infoE(void) -{ - fixme("_ZTVN10__cxxabiv120__si_class_type_infoE() triggered."); - return (void *)0; -} - -// typeinfo for int -extern "C" void *_ZTIi(void) -{ - fixme("_ZTIi() triggered."); - return (void *)0; -} - -// typeinfo for unsigned char* -extern "C" void *_ZTIPh(void) -{ - fixme("_ZTIPh() triggered."); - return (void *)0; -} - -// typeinfo for char const* -extern "C" void *_ZTIPKc(void) -{ - fixme("_ZTIPKc() triggered."); - return (void *)0; -} diff --git a/Library/libstdc++/class_type_info.cpp b/Library/libstdc++/class_type_info.cpp new file mode 100644 index 0000000..4e909e1 --- /dev/null +++ b/Library/libstdc++/class_type_info.cpp @@ -0,0 +1,103 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include + +namespace __cxxabiv1 +{ + __class_type_info::~__class_type_info() {} + + bool __class_type_info::__do_upcast(const __class_type_info *Destination, + const void *Object, + __upcast_result &__restrict Result) const + { + if (*this != *Destination) + return false; + + Result.dst_ptr = Object; + Result.base_type = nonvirtual_base_type; + Result.part2dst = __contained_public; + return true; + } + + bool __class_type_info::__do_upcast(const __class_type_info *DestinationType, + void **ObjectPointer) const + { + __upcast_result Result(__vmi_class_type_info::__flags_unknown_mask); + + __do_upcast(DestinationType, *ObjectPointer, Result); + + if (!((Result.part2dst & + __class_type_info::__contained_public) == + __class_type_info::__contained_public)) + return false; + + *ObjectPointer = const_cast(Result.dst_ptr); + return true; + } + + bool __class_type_info::__do_catch(const type_info *ThrowType, + void **ThrowObject, + unsigned Outer) const + { + if (*this == *ThrowType) + return true; + + if (Outer >= 4) + return false; + + return ThrowType->__do_upcast(this, ThrowObject); + } + + bool __class_type_info::__do_dyncast(ptrdiff_t, + __sub_kind AccessPath, + const __class_type_info *DestinationType, + const void *ObjectPointer, + const __class_type_info *SourceType, + const void *SourcePointer, + __dyncast_result &__restrict Result) const + { + if (ObjectPointer == SourcePointer && + *this == *SourceType) + { + Result.whole2src = AccessPath; + return false; + } + + if (*this == *DestinationType) + { + Result.dst_ptr = ObjectPointer; + Result.whole2dst = AccessPath; + Result.dst2src = __not_contained; + return false; + } + + return false; + } + + __class_type_info::__sub_kind __class_type_info::__do_find_public_src(ptrdiff_t, + const void *ObjectPointer, + const __class_type_info *, + const void *SourcePointer) const + { + if (SourcePointer == ObjectPointer) + return __contained_public; + + return __not_contained; + } +} diff --git a/Library/libstdc++/cxxabi.cpp b/Library/libstdc++/cxxabi.cpp new file mode 100644 index 0000000..68ff010 --- /dev/null +++ b/Library/libstdc++/cxxabi.cpp @@ -0,0 +1,221 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include + +#include "../../kernel.h" + +void __dso_handle_stub() { stub; } + +/* extern */ void *__dso_handle = (void *)&__dso_handle_stub; + +namespace __cxxabiv1 +{ + atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS]; + uarch_t __atexit_func_count = 0; + + __cxa_eh_globals *__cxa_get_globals() noexcept + { + return &GetCurrentCPU()->EHGlobals; + } + + extern "C" int __cxa_atexit(void (*f)(void *), void *objptr, void *dso) + { + debug("Registering atexit function %p( %p, %p )", + f, objptr, dso); + + if (__atexit_func_count >= ATEXIT_MAX_FUNCS) + return -1; + __atexit_funcs[__atexit_func_count].destructor_func = f; + __atexit_funcs[__atexit_func_count].obj_ptr = objptr; + __atexit_funcs[__atexit_func_count].dso_handle = dso; + __atexit_func_count++; + return 0; + } + + extern "C" void __cxa_finalize(void *f) + { + fixme("__cxa_finalize( %p ) called.", f); + uarch_t i = __atexit_func_count; + if (!f) + { + while (i--) + if (__atexit_funcs[i].destructor_func) + (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); + + return; + } + + while (i--) + if (__atexit_funcs[i].destructor_func == f) + { + (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); + __atexit_funcs[i].destructor_func = 0; + } + } + + extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, _Unwind_Exception *ue_header, _Unwind_Context *context) + { + fixme("__gxx_personality_v0( %d %p %p %p %p ) called.", version, actions, exception_class, ue_header, context); + return _URC_NO_REASON; + } + + extern "C" void *__cxa_begin_catch(void *thrown_object) noexcept + { + function("%p", thrown_object); + + __cxa_exception *Exception = (__cxa_exception *)thrown_object - 1; + __cxa_eh_globals *Globals = __cxa_get_globals(); + + Exception->handlerCount++; + Globals->uncaughtExceptions--; + + Exception->nextException = Globals->caughtExceptions; + Globals->caughtExceptions = Exception; + return Exception + 1; + } + + extern "C" void __cxa_end_catch() + { + fixme("__cxa_end_catch() called."); + } + + static __always_inline inline size_t align_exception_allocation_size(size_t a, size_t b) + { + return (a + b - 1) & ~(b - 1); + } + + static __always_inline inline void INIT_EXCEPTION_CLASS(_Unwind_Exception_Class *c) + { + char *ptr = (char *)c; + ptr[0] = 'G'; + ptr[1] = 'N'; + ptr[2] = 'U'; + ptr[3] = 'C'; + ptr[4] = 'C'; + ptr[5] = '+'; + ptr[6] = '+'; + ptr[7] = '\0'; + } + + void unexpected_header_stub() { fixme("unexpected() called."); } + + void terminate_header_stub() + { + if (TaskManager && !TaskManager->IsPanic()) + { + TaskManager->KillThread(TaskManager->GetCurrentThread(), Tasking::KILL_CXXABI_EXCEPTION); + TaskManager->Schedule(); + } + + error("No task manager to kill thread!"); + CPU::Stop(); /* FIXME: Panic */ + } + + void exception_cleanup_stub(_Unwind_Reason_Code Code, + _Unwind_Exception *Exception) + { + fixme("exception_cleanup( %d %p ) called.", + Code, Exception); + } + + extern "C" void *__cxa_allocate_exception(size_t thrown_size) throw() + { + debug("Allocating exception of size %d.", thrown_size); + + size_t alloc_size = align_exception_allocation_size(thrown_size + sizeof(__cxa_exception), alignof(__cxa_exception)); + __cxa_exception *Exception = (__cxa_exception *)kmalloc(alloc_size); + memset(Exception, 0, alloc_size); + return Exception + 1; + } + + extern "C" __noreturn void __cxa_throw(void *thrown_object, + std::type_info *tinfo, + void (*dest)(void *)) + { + trace("Throwing exception of type \"%s\". ( object: %p, destructor: %p )", + tinfo->name(), thrown_object, dest); + + __cxa_eh_globals *Globals = __cxa_get_globals(); + Globals->uncaughtExceptions++; + + __cxa_exception *Exception = (__cxa_exception *)thrown_object - 1; + Exception->exceptionType = (std::type_info *)tinfo; + Exception->exceptionDestructor = dest; + Exception->unexpectedHandler = &unexpected_header_stub; + Exception->terminateHandler = &terminate_header_stub; + Exception->unwindHeader.exception_cleanup = &exception_cleanup_stub; + INIT_EXCEPTION_CLASS(&Exception->unwindHeader.exception_class); + Exception->adjustedPtr = thrown_object; + + _Unwind_RaiseException(&Exception->unwindHeader); + __cxa_begin_catch(&Exception->unwindHeader); + + error("Uncaught exception!"); + CPU::Stop(); /* FIXME: Panic */ + } + + extern "C" void __cxa_rethrow() + { + fixme("__cxa_rethrow() called."); + } + + extern "C" void __cxa_pure_virtual() + { + fixme("__cxa_pure_virtual() called."); + } + + extern "C" void __cxa_throw_bad_array_new_length() + { + fixme("__cxa_throw_bad_array_new_length() called."); + } + + extern "C" void __cxa_free_exception(void *thrown_exception) + { + fixme("__cxa_free_exception( %p ) called.", + thrown_exception); + } + + __extension__ typedef int __guard __attribute__((mode(__DI__))); + + extern "C" int __cxa_guard_acquire(__guard *g) + { + fixme("__cxa_guard_acquire( %p ) called.", g); + return !*(char *)(g); + } + + extern "C" void __cxa_guard_release(__guard *g) + { + fixme("__cxa_guard_release( %p ) called.", g); + *(char *)g = 1; + } + + extern "C" void __cxa_guard_abort(__guard *g) + { + fixme("__cxa_guard_abort( %p ) called.", g); + } + + extern "C" __noreturn void __cxa_bad_typeid() + { + fixme("__cxa_bad_typeid() called."); + CPU::Stop(); /* FIXME: Crash the system */ + } +} diff --git a/Execute/Fex/BaseLoad.cpp b/Library/libstdc++/fundamental_type_info.cpp similarity index 71% rename from Execute/Fex/BaseLoad.cpp rename to Library/libstdc++/fundamental_type_info.cpp index 8c98fb2..e4ab1a9 100644 --- a/Execute/Fex/BaseLoad.cpp +++ b/Library/libstdc++/fundamental_type_info.cpp @@ -15,24 +15,9 @@ along with Fennix Kernel. If not, see . */ -#include +#include -#include -#include -#include -#include -#include -#include - -#include "../../kernel.h" -#include "../../Fex.hpp" - -using namespace Tasking; - -namespace Execute +namespace __cxxabiv1 { - void FEXLoad() - { - - } + __fundamental_type_info::~__fundamental_type_info() {} } diff --git a/Library/libstdc++/pbase_type_info.cpp b/Library/libstdc++/pbase_type_info.cpp new file mode 100644 index 0000000..5d1e134 --- /dev/null +++ b/Library/libstdc++/pbase_type_info.cpp @@ -0,0 +1,88 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +namespace __cxxabiv1 +{ + __pbase_type_info::~__pbase_type_info() {} + + bool __pbase_type_info::__do_catch(const type_info *ThrowType, + void **ThrowObject, + unsigned outer) const + { +#ifndef __GXX_RTTI + return false; +#else + if (*this == *ThrowType) + return true; + + if (*ThrowType == typeid(nullptr)) + { + if (typeid(*this) == typeid(__pointer_type_info)) + { + *ThrowObject = nullptr; + return true; + } + else if (typeid(*this) == typeid(__pointer_to_member_type_info)) + { + if (this->Pointee->__is_function_p()) + { + using pmf_type = void (__pbase_type_info::*)(); + static const pmf_type pmf = nullptr; + *ThrowObject = const_cast(&pmf); + return true; + } + else + { + using pm_type = int __pbase_type_info::*; + static const pm_type pm = nullptr; + *ThrowObject = const_cast(&pm); + return true; + } + } + } + + if (typeid(*this) != typeid(*ThrowType)) + return false; + + if (!(outer & 1)) + return false; + + const __pbase_type_info *ThrownType = + static_cast(ThrowType); + + unsigned TypeFlags = ThrownType->Flags; + + const unsigned FlagQualificationMask = __transaction_safe_mask | __noexcept_mask; + unsigned ThrowFlagQualification = (TypeFlags & FlagQualificationMask); + unsigned CatchFlagQualification = (Flags & FlagQualificationMask); + if (ThrowFlagQualification & ~CatchFlagQualification) + TypeFlags &= CatchFlagQualification; + if (CatchFlagQualification & ~ThrowFlagQualification) + return false; + + if (TypeFlags & ~Flags) + return false; + + if (!(Flags & __const_mask)) + outer &= ~1; + + return __pointer_catch(ThrownType, ThrowObject, outer); +#endif + } +} diff --git a/Library/libstdc++/pointer_type_info.cpp b/Library/libstdc++/pointer_type_info.cpp new file mode 100644 index 0000000..ef51941 --- /dev/null +++ b/Library/libstdc++/pointer_type_info.cpp @@ -0,0 +1,42 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +namespace __cxxabiv1 +{ + __pointer_type_info::~__pointer_type_info() {} + + bool __pointer_type_info::__is_pointer_p() const { return true; } + + bool __pointer_type_info::__pointer_catch(const __pbase_type_info *ThrownType, + void **ThrowObject, + unsigned Outer) const + { +#ifndef __GXX_RTTI + return false; +#else + if (Outer < 2 && *this->Pointee == typeid(void)) + return !ThrownType->Pointee->__is_function_p(); + + return __pbase_type_info::__pointer_catch(ThrownType, + ThrowObject, + Outer); +#endif + } + +} diff --git a/Library/libstdc++/si_class_type_info.cpp b/Library/libstdc++/si_class_type_info.cpp new file mode 100644 index 0000000..d6048c7 --- /dev/null +++ b/Library/libstdc++/si_class_type_info.cpp @@ -0,0 +1,102 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include + +namespace __cxxabiv1 +{ + template + inline const T *adjust_pointer(const void *Base, + ptrdiff_t Offset) + { + return reinterpret_cast(reinterpret_cast(Base) + Offset); + } + + __si_class_type_info::~__si_class_type_info() {} + + __class_type_info::__sub_kind __si_class_type_info:: + __do_find_public_src(ptrdiff_t SourceToDestination, + const void *ObjectPointer, + const __class_type_info *SourceType, + const void *SourcePointer) const + { + if (SourcePointer == ObjectPointer && *this == *SourceType) + return __contained_public; + + return this->BaseType->__do_find_public_src(SourceToDestination, + ObjectPointer, + SourceType, + SourcePointer); + } + + bool __si_class_type_info::__do_dyncast(ptrdiff_t SourceToDestination, + __sub_kind AccessPath, + const __class_type_info *DestinationType, + const void *ObjectPointer, + const __class_type_info *SourceType, + const void *SourcePointer, + __dyncast_result &__restrict Result) const + { + if (*this == *DestinationType) + { + Result.dst_ptr = ObjectPointer; + Result.whole2dst = AccessPath; + + if (SourceToDestination == -2) + { + Result.dst2src = __not_contained; + return false; + } + + if (SourceToDestination >= 0) + { + Result.dst2src = adjust_pointer(ObjectPointer, + SourceToDestination) == SourcePointer + ? __contained_public + : __not_contained; + } + + return false; + } + + if (ObjectPointer == SourcePointer && + *this == *SourceType) + { + Result.whole2src = AccessPath; + return false; + } + + return this->BaseType->__do_dyncast(SourceToDestination, + AccessPath, + DestinationType, + ObjectPointer, + SourceType, + SourcePointer, + Result); + } + + bool __si_class_type_info::__do_upcast(const __class_type_info *Destination, + const void *ObjectPointer, + __upcast_result &__restrict Result) const + { + if (__class_type_info::__do_upcast(Destination, ObjectPointer, Result)) + return true; + + return this->BaseType->__do_upcast(Destination, ObjectPointer, Result); + } +} diff --git a/Execute/Elf/Dyn.cpp b/Library/libstdc++/unwind.cpp similarity index 57% rename from Execute/Elf/Dyn.cpp rename to Library/libstdc++/unwind.cpp index a7c35a1..6d0ce80 100644 --- a/Execute/Elf/Dyn.cpp +++ b/Library/libstdc++/unwind.cpp @@ -15,30 +15,27 @@ along with Fennix Kernel. If not, see . */ -#include - -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "../../kernel.h" -#include "../../Fex.hpp" -using namespace Tasking; +using namespace __cxxabiv1; -namespace Execute +#if (1) /* Stubs if libgcc is not present */ +extern "C" _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *Exception) { - ELFBaseLoad ELFLoadDyn(void *BaseImage, - VirtualFileSystem::File &ExFile, - Tasking::PCB *Process) - { - UNUSED(BaseImage); - UNUSED(ExFile); - UNUSED(Process); - fixme("Not implemented"); - return {}; - } + fixme("_Unwind_RaiseException( %p ) called.", Exception); + error("Unhandled exception."); + return _URC_FATAL_PHASE1_ERROR; + // return _URC_NO_REASON; } + +extern "C" void _Unwind_Resume(struct _Unwind_Exception *Exception) +{ + fixme("_Unwind_Resume( %p ) called.", Exception); +} +#endif diff --git a/Library/errno.cpp b/Library/std/errno.cpp similarity index 100% rename from Library/errno.cpp rename to Library/std/errno.cpp diff --git a/Library/std/typeinfo.cpp b/Library/std/typeinfo.cpp new file mode 100644 index 0000000..ef20fd0 --- /dev/null +++ b/Library/std/typeinfo.cpp @@ -0,0 +1,39 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include + +namespace std +{ + type_info::~type_info() {} + + bool type_info::__do_catch(const type_info *ThrowType, + void **ThrowObject, + unsigned Outer) const + { + stub; + return false; + } + + bool type_info::__do_upcast(const __cxxabiv1::__class_type_info *Target, + void **ObjectPointer) const + { + stub; + return false; + } +} diff --git a/Makefile b/Makefile index 7cd3973..74dd6e9 100644 --- a/Makefile +++ b/Makefile @@ -27,29 +27,26 @@ S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/i386/ s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*") C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*") CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*") -RS_SOURCES = $(shell find ./ -type f -name '*.rs' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*") else ifeq ($(OSARCH), i386) ASM_SOURCES = $(shell find ./ -type f -name '*.asm' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*") S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*") s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*") C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*") CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*") -RS_SOURCES = $(shell find ./ -type f -name '*.rs' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*") else ifeq ($(OSARCH), aarch64) ASM_SOURCES = $(shell find ./ -type f -name '*.asm' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*") S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*") s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*") C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*") CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*") -RS_SOURCES = $(shell find ./ -type f -name '*.rs' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*") endif HEADERS = $(sort $(dir $(wildcard ./include/*))) $(sort $(dir $(wildcard ./include_std/*))) -OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(RS_SOURCES:.rs=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(s_SOURCES:.s=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o) +OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(s_SOURCES:.s=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su) GCNO_OBJ = $(C_SOURCES:.c=.gcno) $(CPP_SOURCES:.cpp=.gcno) INCLUDE_DIR = -I./include -I./include_std -LDFLAGS := -Wl,-Map kernel.map -shared -nostdlib -nodefaultlibs -nolibc +LDFLAGS := -Wl,-Map kernel.map -static -nostdlib -nodefaultlibs -nolibc # Disable all warnings by adding "-w" in WARNCFLAG and if you want to treat the warnings as errors, add "-Werror" WARNCFLAG = -Wall -Wextra \ @@ -76,9 +73,8 @@ CFLAG_STACK_PROTECTOR := -fstack-protector-all LDFLAGS += -TArchitecture/amd64/linker.ld \ -fno-pic -fno-pie \ -Wl,-static,--no-dynamic-linker,-ztext \ - -nostdlib -nodefaultlibs -nolibc \ -zmax-page-size=0x1000 \ - -Wl,-Map kernel.map -shared + -Wl,-Map kernel.map else ifeq ($(OSARCH), i386) @@ -89,9 +85,8 @@ CFLAG_STACK_PROTECTOR := -fstack-protector-all LDFLAGS += -TArchitecture/i386/linker.ld \ -fno-pic -fno-pie \ -Wl,-static,--no-dynamic-linker,-ztext \ - -nostdlib -nodefaultlibs -nolibc \ -zmax-page-size=0x1000 \ - -Wl,-Map kernel.map -shared + -Wl,-Map kernel.map else ifeq ($(OSARCH), aarch64) @@ -99,9 +94,8 @@ CFLAGS += -pipe -fno-builtin -Wstack-protector -Daa64 -fPIC -mno-outline-atomics CFLAG_STACK_PROTECTOR := -fstack-protector-all LDFLAGS += -TArchitecture/aarch64/linker.ld -fPIC -pie \ -Wl,-static,--no-dynamic-linker,-ztext \ - -nostdlib -nodefaultlibs -nolibc \ -zmax-page-size=0x1000 \ - -Wl,-Map kernel.map -static + -Wl,-Map kernel.map endif @@ -158,11 +152,7 @@ $(KERNEL_FILENAME): $(OBJ) # https://gcc.gnu.org/projects/cxx-status.html %.o: %.cpp $(HEADERS) $(info Compiling $<) - $(CPP) $(CFLAGS) $(CFLAG_STACK_PROTECTOR) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@ -fno-rtti - -%.o: %.rs $(HEADERS) $(RUST_TARGET_PATH) - $(info Compiling $<) - $(RUSTC) $< -C panic=abort -C soft-float --emit=obj -o $@ + $(CPP) $(CFLAGS) $(CFLAG_STACK_PROTECTOR) $(WARNCFLAG) -std=c++20 -c $< -o $@ -fno-exceptions -fno-rtti %.o: %.asm ifeq ($(OSARCH), aarch64) diff --git a/Network/NetworkController.cpp b/Network/NetworkController.cpp index db67ae3..7f759e0 100644 --- a/Network/NetworkController.cpp +++ b/Network/NetworkController.cpp @@ -168,26 +168,6 @@ namespace NetworkInterfaceManager fixme("Stop network stack"); } - ReadFSFunction(NetRead) - { - UNUSED(node); - UNUSED(Offset); - UNUSED(Size); - UNUSED(Buffer); - fixme("Not implemented."); - return Size; - } - - WriteFSFunction(NetWrite) - { - UNUSED(node); - UNUSED(Offset); - UNUSED(Size); - UNUSED(Buffer); - fixme("Not implemented."); - return Size; - } - void CallStartNetworkStackWrapper() { NIManager->StartNetworkStack(); } void NetworkInterface::StartService() diff --git a/Recovery/RecoveryMain.cpp b/Recovery/RecoveryMain.cpp index 3a668f4..87ebe39 100644 --- a/Recovery/RecoveryMain.cpp +++ b/Recovery/RecoveryMain.cpp @@ -79,18 +79,18 @@ namespace Recovery return; } - void *PCMRaw = KernelAllocator.RequestPages(TO_PAGES(pcm.node->Length + 1)); - memcpy(PCMRaw, (void *)pcm.node->Address, pcm.node->Length); + void *PCMRaw = KernelAllocator.RequestPages(TO_PAGES(pcm.GetLength() + 1)); + vfs->Read(pcm, (uint8_t *)PCMRaw, pcm.GetLength()); KernelCallback callback{}; callback.Reason = SendReason; callback.AudioCallback.Send.Data = (uint8_t *)PCMRaw; - callback.AudioCallback.Send.Length = pcm.node->Length; + callback.AudioCallback.Send.Length = pcm.GetLength(); debug("Playing audio..."); int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback); UNUSED(status); debug("Audio played! %d", status); - KernelAllocator.FreePages((void *)PCMRaw, TO_PAGES(pcm.node->Length + 1)); + KernelAllocator.FreePages((void *)PCMRaw, TO_PAGES(pcm.GetLength() + 1)); vfs->Close(pcm); TEXIT(0); } @@ -364,8 +364,8 @@ namespace Recovery KernelRecovery::~KernelRecovery() { debug("Destructor called"); - TaskManager->KillThread(guiThread, 0); - TaskManager->KillThread(recoveryThread, 0); + TaskManager->KillThread(guiThread, Tasking::KILL_SUCCESS); + TaskManager->KillThread(recoveryThread, Tasking::KILL_SUCCESS); delete gui, gui = nullptr; } } diff --git a/SystemCalls/Native.cpp b/SystemCalls/Native.cpp index 1164a36..4920f27 100644 --- a/SystemCalls/Native.cpp +++ b/SystemCalls/Native.cpp @@ -26,7 +26,6 @@ #include "../syscalls.h" #include "../kernel.h" -#include "../../Userspace/libs/include/libsys/base.h" /* KCtl */ #include "../ipc.h" using InterProcessCommunication::IPC; @@ -40,557 +39,623 @@ using Tasking::TTL::Untrusted; static inline bool CheckTrust(int TrustLevel) { - Token token = TaskManager->GetCurrentThread()->Security.UniqueToken; - if (TaskManager->GetSecurityManager()->IsTokenTrusted(token, TrustLevel)) - return true; + Token token = TaskManager->GetCurrentThread()->Security.UniqueToken; + if (likely(TaskManager->GetSecurityManager()->IsTokenTrusted(token, TrustLevel))) + return true; - warn("Thread %s(%lld) tried to access a system call \"%s\" with insufficient trust level", - TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID, - KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0)))); - debug("Token: token=%#lx, trust=%d", token, TaskManager->GetSecurityManager()->GetTokenTrustLevel(token)); - return false; + warn("Thread %s(%lld) tried to access a system call \"%s\" with insufficient trust level", + TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID, + KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0)))); + debug("token=%#lx, trust=%d", token, TaskManager->GetSecurityManager()->GetTokenTrustLevel(token)); + return false; } static int sys_exit(SyscallsFrame *Frame, int code) { - /* Allow everyone to exit */ - if (!CheckTrust(TrustedByKernel | Trusted | Untrusted | UnknownTrustLevel)) - return SYSCALL_ACCESS_DENIED; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted | UnknownTrustLevel)) + return SYSCALL_ACCESS_DENIED; - trace("Userspace thread %s(%lld) exited with code %#llx", TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID, code); - TaskManager->GetCurrentThread()->ExitCode = code; - TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated; - UNUSED(Frame); - return SYSCALL_OK; + trace("Userspace thread %s(%lld) exited with code %#llx", TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID, code); + TaskManager->GetCurrentThread()->ExitCode = code; + TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated; + TaskManager->Schedule(); + + UNUSED(Frame); + return SYSCALL_OK; } static int sys_print(SyscallsFrame *Frame, char Char, int Index) { - /* Only trusted threads can write to the kernel console */ - if (!CheckTrust(TrustedByKernel | Trusted)) - return SYSCALL_ACCESS_DENIED; + if (!CheckTrust(TrustedByKernel | Trusted)) + return SYSCALL_ACCESS_DENIED; - char ret = Display->Print(Char, Index, true); - if (!Config.BootAnimation && Index == 0) + char ret = Display->Print(Char, Index, true); + if (!Config.BootAnimation && Index == 0) #ifdef DEBUG - Display->SetBuffer(Index); + Display->SetBuffer(Index); #else - if (Char == '\n') - Display->SetBuffer(Index); + if (Char == '\n') + Display->SetBuffer(Index); #endif - UNUSED(Frame); - return ret; + UNUSED(Frame); + return ret; } static uintptr_t sys_request_pages(SyscallsFrame *Frame, size_t Count) { - /* Allow everyone to request pages */ - if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) - return SYSCALL_ACCESS_DENIED; - UNUSED(Frame); - return (uintptr_t)TaskManager->GetCurrentThread()->Memory->RequestPages(Count + 1, true); + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; + + UNUSED(Frame); + return (uintptr_t)TaskManager->GetCurrentThread()->Memory->RequestPages(Count + 1, true); } static int sys_free_pages(SyscallsFrame *Frame, uintptr_t Address, size_t Count) { - /* Allow everyone to free pages */ - if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) - return SYSCALL_ACCESS_DENIED; - TaskManager->GetCurrentThread()->Memory->FreePages((void *)Address, Count + 1); - UNUSED(Frame); - return SYSCALL_OK; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; + + TaskManager->GetCurrentThread()->Memory->FreePages((void *)Address, Count + 1); + UNUSED(Frame); + return SYSCALL_OK; } static int sys_detach_address(SyscallsFrame *Frame, uintptr_t Address) { - /* Only trusted threads can detach allocated addresses */ - if (!CheckTrust(TrustedByKernel | Trusted)) - return SYSCALL_ACCESS_DENIED; - TaskManager->GetCurrentThread()->Memory->DetachAddress((void *)Address); - UNUSED(Frame); - return SYSCALL_OK; + if (!CheckTrust(TrustedByKernel | Trusted)) + return SYSCALL_ACCESS_DENIED; + + TaskManager->GetCurrentThread()->Memory->DetachAddress((void *)Address); + UNUSED(Frame); + return SYSCALL_OK; +} + +static int sys_memory_map(SyscallsFrame *Frame, uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags) +{ + if (!CheckTrust(TrustedByKernel)) + return SYSCALL_ACCESS_DENIED; + + if (Flags > 7) /* (MAP_PRESENT | MAP_WRITABLE | MAP_USER) */ + return SYSCALL_INVALID_ARGUMENT; + + Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable; + { + Memory::Virtual vmm = Memory::Virtual(PageTable); + vmm.Map((void *)VirtualAddress, + (void *)PhysicalAddress, + Size, Flags); + } + + UNUSED(Frame); + return SYSCALL_OK; +} + +static int sys_memory_unmap(SyscallsFrame *Frame, uintptr_t VirtualAddress, size_t Size) +{ + if (!CheckTrust(TrustedByKernel)) + return SYSCALL_ACCESS_DENIED; + + Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable; + { + Memory::Virtual vmm = Memory::Virtual(PageTable); + vmm.Unmap((void *)VirtualAddress, + Size); + } + + UNUSED(Frame); + return SYSCALL_OK; } static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) { - if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) - return SYSCALL_ACCESS_DENIED; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; - switch (Command) - { - case KCTL_GET_PID: - return TaskManager->GetCurrentThread()->Parent->ID; - case KCTL_GET_TID: - return TaskManager->GetCurrentThread()->ID; - case KCTL_GET_PAGE_SIZE: - return PAGE_SIZE; - case KCTL_IS_CRITICAL: - return TaskManager->GetCurrentThread()->Security.IsCritical; - case KCTL_REGISTER_ELF_LIB: - { - if (!CheckTrust(TrustedByKernel | Trusted)) - return SYSCALL_ACCESS_DENIED; - char *Identifier = (char *)Arg1; - const char *Path = (const char *)Arg2; + switch (Command) + { + case KCTL_GET_PID: + return TaskManager->GetCurrentThread()->Parent->ID; + case KCTL_GET_TID: + return TaskManager->GetCurrentThread()->ID; + case KCTL_GET_PAGE_SIZE: + return PAGE_SIZE; + case KCTL_IS_CRITICAL: + return TaskManager->GetCurrentThread()->Security.IsCritical; + case KCTL_REGISTER_ELF_LIB: + { + if (!CheckTrust(TrustedByKernel | Trusted)) + return SYSCALL_ACCESS_DENIED; - if (!Identifier || !Path) - return SYSCALL_INVALID_ARGUMENT; + char *Identifier = (char *)Arg1; + const char *Path = (const char *)Arg2; - std::string FullPath = Path; - int retries = 0; - RetryReadPath: - debug("KCTL_REGISTER_ELF_LIB: Trying to open %s", FullPath.c_str()); - VirtualFileSystem::File f = vfs->Open(FullPath.c_str()); + if (!Identifier || !Path) + return SYSCALL_INVALID_ARGUMENT; - if (!f.IsOK()) - { - FullPath.clear(); - switch (retries) - { - case 0: - FullPath = "/lib/"; - break; - case 1: - FullPath = "/usr/lib/"; - break; - case 2: - FullPath = "/"; - break; - case 3: - { - // TODO: Check process binary path - break; - } - default: - { - vfs->Close(f); - return SYSCALL_INVALID_ARGUMENT; - } - } - FullPath += Path; - vfs->Close(f); - retries++; - goto RetryReadPath; - } + std::string FullPath = Path; + int retries = 0; + RetryReadPath: + debug("KCTL_REGISTER_ELF_LIB: Trying to open %s", FullPath.c_str()); + VirtualFileSystem::File f = vfs->Open(FullPath.c_str()); - vfs->Close(f); - if (Execute::AddLibrary(Identifier, (void *)f.node->Address, f.node->Length)) - return SYSCALL_OK; - else - return SYSCALL_INTERNAL_ERROR; - } - case KCTL_GET_ELF_LIB_FILE: - { - if (!CheckTrust(TrustedByKernel | Trusted)) - return SYSCALL_ACCESS_DENIED; - char *Identifier = (char *)Arg1; - if (!Identifier) - return 0; + if (!f.IsOK()) + { + FullPath.clear(); + switch (retries) + { + case 0: + FullPath = "/lib/"; + break; + case 1: + FullPath = "/usr/lib/"; + break; + case 2: + FullPath = "/"; + break; + case 3: + { + VirtualFileSystem::Node *cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory; + FullPath = vfs->GetPathFromNode(cwd).get(); + break; + } + default: + { + vfs->Close(f); + return SYSCALL_INVALID_ARGUMENT; + } + } + FullPath += Path; + vfs->Close(f); + retries++; + goto RetryReadPath; + } - Execute::SharedLibraries lib = Execute::GetLibrary(Identifier); - if (!lib.Address) - { - debug("Failed to get library address %#lx", (uintptr_t)lib.Address); - } + if (Execute::AddLibrary(Identifier, f)) + { + vfs->Close(f); + return SYSCALL_OK; + } + else + { + vfs->Close(f); + return SYSCALL_INTERNAL_ERROR; + } + } + case KCTL_GET_ELF_LIB_MEMORY_IMAGE: + { + if (!CheckTrust(TrustedByKernel | Trusted)) + return SYSCALL_ACCESS_DENIED; - debug("Returning library address %#lx (%s)", (uintptr_t)lib.Address, Identifier); - return (uintptr_t)lib.Address; - } - case KCTL_GET_ELF_LIB_MEMORY_IMAGE: - { - if (!CheckTrust(TrustedByKernel | Trusted)) - return SYSCALL_ACCESS_DENIED; - char *Identifier = (char *)Arg1; - if (!Identifier) - return 0; + char *Identifier = (char *)Arg1; + if (!Identifier) + return 0; - Execute::SharedLibraries lib = Execute::GetLibrary(Identifier); + Execute::SharedLibrary lib = Execute::GetLibrary(Identifier); - if (!lib.MemoryImage) - { - debug("Failed to get library memory image %#lx", (uintptr_t)lib.MemoryImage); - } + if (!lib.MemoryImage) + { + debug("Failed to get library memory image %#lx", (uintptr_t)lib.MemoryImage); + } - debug("Returning memory image %#lx (%s)", (uintptr_t)lib.MemoryImage, Identifier); - return (uintptr_t)lib.MemoryImage; - } - case KCTL_GET_FRAMEBUFFER_BUFFER: - return r_cst(uint64_t, Display->GetBuffer(0)->Buffer); - case KCTL_GET_FRAMEBUFFER_WIDTH: - return Display->GetBuffer(0)->Width; - case KCTL_GET_FRAMEBUFFER_HEIGHT: - return Display->GetBuffer(0)->Height; - case KCTL_GET_FRAMEBUFFER_SIZE: - return Display->GetBuffer(0)->Size; + debug("Returning memory image %#lx (%s)", (uintptr_t)lib.MemoryImage, Identifier); + return (uintptr_t)lib.MemoryImage; + } + case KCTL_GET_ABSOLUTE_PATH: + { + if (!CheckTrust(TrustedByKernel | Trusted)) + return SYSCALL_ACCESS_DENIED; - default: - { - warn("KernelCTL: Unknown command: %lld", Command); - return SYSCALL_INVALID_ARGUMENT; - } - } + char *Identifier = (char *)Arg1; + void *Buffer = (void *)Arg2; + size_t BufferSize = Arg3; - UNUSED(Arg1); - UNUSED(Arg2); - UNUSED(Arg3); - UNUSED(Arg4); - UNUSED(Frame); -} + if (!Identifier || !Buffer || !BufferSize) + return SYSCALL_INVALID_ARGUMENT; -static int sys_ipc(SyscallsFrame *Frame, enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size) -{ - /* Allow everyone to use IPC */ - if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) - return SYSCALL_ACCESS_DENIED; - UNUSED(Frame); - return TaskManager->GetCurrentProcess()->IPC->HandleSyscall(Command, Type, ID, Flags, Buffer, Size); + Execute::SharedLibrary lib = Execute::GetLibrary(Identifier); + + if (!lib.MemoryImage) + return SYSCALL_INTERNAL_ERROR; + + if (BufferSize < sizeof(lib.Path)) + return SYSCALL_INVALID_ARGUMENT; + + memcpy(Buffer, lib.Path, sizeof(lib.Path)); + return SYSCALL_OK; + } + default: + { + warn("KernelCTL: Unknown command: %lld", Command); + return SYSCALL_INVALID_ARGUMENT; + } + } + + UNUSED(Arg1); + UNUSED(Arg2); + UNUSED(Arg3); + UNUSED(Arg4); + UNUSED(Frame); } static uint64_t sys_file_open(SyscallsFrame *Frame, const char *Path, uint64_t Flags) { - debug("(Path: %s, Flags: %#lx)", Path, Flags); - VirtualFileSystem::Node *cwd = nullptr; - if (vfs->PathIsRelative(Path)) - cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory; - else - cwd = vfs->GetRootNode(); + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; - VirtualFileSystem::File KPObj = vfs->Open(Path, cwd); - if (!KPObj.IsOK()) - { - debug("Failed to open file %s (%d)", Path, KPObj.Status); - vfs->Close(KPObj); - return SYSCALL_INTERNAL_ERROR; - } + debug("(Path: %s, Flags: %#lx)", Path, Flags); + VirtualFileSystem::Node *cwd = nullptr; + if (vfs->PathIsRelative(Path)) + cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory; + else + cwd = vfs->GetRootNode(); - VirtualFileSystem::File *KernelPrivate = (VirtualFileSystem::File *)TaskManager->GetCurrentThread()->Memory->RequestPages(TO_PAGES(sizeof(VirtualFileSystem::File))); - *KernelPrivate = KPObj; - debug("Opened file %s (%d)", KPObj.Name, KPObj.Status); - return (uint64_t)KernelPrivate; - UNUSED(Frame); - UNUSED(Flags); + VirtualFileSystem::File KPObj = vfs->Open(Path, cwd); + if (!KPObj.IsOK()) + { + debug("Failed to open file %s (%d)", Path, KPObj.Status); + vfs->Close(KPObj); + return SYSCALL_INTERNAL_ERROR; + } + + VirtualFileSystem::File *KernelPrivate = (VirtualFileSystem::File *)TaskManager->GetCurrentThread()->Memory->RequestPages(TO_PAGES(sizeof(VirtualFileSystem::File))); + *KernelPrivate = KPObj; + debug("Opened file %s (%d)", KPObj.Name, KPObj.Status); + return (uint64_t)KernelPrivate; + UNUSED(Frame); + UNUSED(Flags); } static int sys_file_close(SyscallsFrame *Frame, void *KernelPrivate) { - debug("(KernelPrivate: %#lx)", KernelPrivate); + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; - if (KernelPrivate) - { - VirtualFileSystem::File KPObj = *(VirtualFileSystem::File *)KernelPrivate; - debug("Closed file %s (%d)", KPObj.Name, KPObj.Status); - vfs->Close(KPObj); - TaskManager->GetCurrentThread()->Memory->FreePages(KernelPrivate, TO_PAGES(sizeof(VirtualFileSystem::File))); - return SYSCALL_OK; - } - return SYSCALL_INVALID_ARGUMENT; - UNUSED(Frame); + debug("(KernelPrivate: %#lx)", KernelPrivate); + + if (KernelPrivate) + { + VirtualFileSystem::File KPObj = *(VirtualFileSystem::File *)KernelPrivate; + debug("Closed file %s (%d)", KPObj.Name, KPObj.Status); + vfs->Close(KPObj); + TaskManager->GetCurrentThread()->Memory->FreePages(KernelPrivate, TO_PAGES(sizeof(VirtualFileSystem::File))); + return SYSCALL_OK; + } + return SYSCALL_INVALID_ARGUMENT; + UNUSED(Frame); } -static uint64_t sys_file_read(SyscallsFrame *Frame, void *KernelPrivate, uint64_t Offset, uint8_t *Buffer, uint64_t Size) +static uint64_t sys_file_read(SyscallsFrame *Frame, void *KernelPrivate, uint8_t *Buffer, uint64_t Size) { - if (KernelPrivate == nullptr) - return 0; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; - debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Offset, Buffer, Size); - return vfs->Read(*(VirtualFileSystem::File *)KernelPrivate, (size_t)Offset, Buffer, (size_t)Size); - UNUSED(Frame); + if (KernelPrivate == nullptr) + return 0; + + debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Buffer, Size); + return vfs->Read(*(VirtualFileSystem::File *)KernelPrivate, Buffer, (size_t)Size); + UNUSED(Frame); } -static uint64_t sys_file_write(SyscallsFrame *Frame, void *KernelPrivate, uint64_t Offset, uint8_t *Buffer, uint64_t Size) +static uint64_t sys_file_write(SyscallsFrame *Frame, void *KernelPrivate, uint8_t *Buffer, uint64_t Size) { - if (KernelPrivate == nullptr) - return 0; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; - debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Offset, Buffer, Size); - return vfs->Write(*(VirtualFileSystem::File *)KernelPrivate, (size_t)Offset, Buffer, (size_t)Size); - UNUSED(Frame); + if (KernelPrivate == nullptr) + return 0; + + debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Buffer, Size); + return vfs->Write(*(VirtualFileSystem::File *)KernelPrivate, Buffer, (size_t)Size); + UNUSED(Frame); } -static uint64_t sys_file_seek(SyscallsFrame *Frame, void *KernelPrivate, uint64_t Offset, int Whence) +static off_t sys_file_seek(SyscallsFrame *Frame, void *KernelPrivate, off_t Offset, int Whence) { - if (KernelPrivate == nullptr) - return 0; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; - debug("(KernelPrivate: %#lx, Offset: %#lx, Whence: %d)", KernelPrivate, Offset, Whence); - VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate; + if (KernelPrivate == nullptr) + return 0; - if (KPObj->node->Operator->Seek == nullptr) - return SYSCALL_INTERNAL_ERROR; + debug("(KernelPrivate: %#lx, Offset: %#lx, Whence: %d)", KernelPrivate, Offset, Whence); + VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate; - uint64_t ret = KPObj->node->Operator->Seek(KPObj->node, (size_t)Offset, (uint8_t)Whence); - debug("Seek %s %ld", KPObj->Name, ret); - return ret; - UNUSED(Frame); + off_t ret = vfs->Seek(*KPObj, (off_t)Offset, (uint8_t)Whence); + debug("Seek %s %ld", KPObj->Name, ret); + return ret; + UNUSED(Frame); } static int sys_file_status(SyscallsFrame *Frame) { - fixme("sys_file_status: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; + + fixme("sys_file_status: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; +} + +static int sys_ipc(SyscallsFrame *Frame, enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size) +{ + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; + + UNUSED(Frame); + return TaskManager->GetCurrentProcess()->IPC->HandleSyscall(Command, Type, ID, Flags, Buffer, Size); } static int sys_sleep(SyscallsFrame *Frame, uint64_t Milliseconds) { - UNUSED(Frame); - if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) - return SYSCALL_ACCESS_DENIED; - TaskManager->Sleep(Milliseconds); - return 0; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; + + UNUSED(Frame); + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; + TaskManager->Sleep(Milliseconds); + return 0; } static int sys_fork(SyscallsFrame *Frame) { - UNUSED(Frame); - if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) - return SYSCALL_ACCESS_DENIED; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; - Tasking::PCB *Parent = TaskManager->GetCurrentThread()->Parent; - Tasking::TCB *Thread = TaskManager->GetCurrentThread(); + Tasking::PCB *Parent = TaskManager->GetCurrentThread()->Parent; + Tasking::TCB *Thread = TaskManager->GetCurrentThread(); - Tasking::PCB *NewProcess = TaskManager->CreateProcess(Parent, - Parent->Name, - Parent->Security.TrustLevel, - Parent->ELFSymbolTable ? Parent->ELFSymbolTable->GetImage() : nullptr); + Tasking::PCB *NewProcess = TaskManager->CreateProcess(Parent, + Parent->Name, + Parent->Security.TrustLevel, + Parent->ELFSymbolTable ? Parent->ELFSymbolTable->GetImage() : nullptr); - if (!NewProcess) - { - error("Failed to create process for fork"); - return SYSCALL_ERROR; - } + if (!NewProcess) + { + error("Failed to create process for fork"); + return SYSCALL_ERROR; + } - strncpy(NewProcess->Name, Parent->Name, sizeof(NewProcess->Name)); - NewProcess->IPC->Fork(Parent->IPC); // FIXME: Do we need to do this? + strncpy(NewProcess->Name, Parent->Name, sizeof(NewProcess->Name)); + NewProcess->IPC->Fork(Parent->IPC); - Tasking::TCB *NewThread = TaskManager->CreateThread(NewProcess, - 0, - nullptr, - nullptr, - std::vector(), - 0, - Thread->Info.Architecture, - Thread->Info.Compatibility, - true); + Tasking::TCB *NewThread = TaskManager->CreateThread(NewProcess, + 0, + nullptr, + nullptr, + std::vector(), + Thread->Info.Architecture, + Thread->Info.Compatibility, + true); - strncpy(NewThread->Name, Thread->Name, sizeof(Thread->Name)); + strncpy(NewThread->Name, Thread->Name, sizeof(Thread->Name)); - if (!NewThread) - { - error("Failed to create thread for fork"); - return SYSCALL_ERROR; - } + if (!NewThread) + { + error("Failed to create thread for fork"); + return SYSCALL_ERROR; + } - static int RetChild = 0; - static uint64_t ReturnAddress = 0; - static uint64_t ChildStackPointer = 0; + static int RetChild = 0; + static uint64_t ReturnAddress = 0; + static uint64_t ChildStackPointer = 0; - TaskManager->Schedule(); + TaskManager->Schedule(); - if (RetChild--) - { - /* We can't just return 0; because the CPUData->SystemCallStack is no longer valid */ - asmv("movq %0, %%rcx\n" - : - : "r"(ReturnAddress)); - asmv("mov %0, %%rsp\n" - : - : "r"(ChildStackPointer)); - asmv("mov %0, %%rbp\n" - : - : "r"(ChildStackPointer)); - asmv("movq $0, %rax\n"); // Return 0 to the child - asmv("swapgs\n"); // Swap GS back to the user GS - asmv("sti\n"); // Enable interrupts - asmv("sysretq\n"); // Return to rcx address in user mode - } - RetChild = 1; - ReturnAddress = Frame->ReturnAddress; - ChildStackPointer = Frame->StackPointer; + if (RetChild--) + { + /* We can't just return 0; because the CPUData->SystemCallStack is no longer valid */ + asmv("movq %0, %%rcx\n" + : + : "r"(ReturnAddress)); + asmv("mov %0, %%rsp\n" + : + : "r"(ChildStackPointer)); + asmv("mov %0, %%rbp\n" + : + : "r"(ChildStackPointer)); + asmv("movq $0, %rax\n"); // Return 0 to the child + asmv("swapgs\n"); // Swap GS back to the user GS + asmv("sti\n"); // Enable interrupts + asmv("sysretq\n"); // Return to rcx address in user mode + } + RetChild = 1; + ReturnAddress = Frame->ReturnAddress; + ChildStackPointer = Frame->StackPointer; - memcpy(NewThread->FPU, Thread->FPU, sizeof(CPU::x64::FXState)); - NewThread->Stack->Fork(Thread->Stack); - NewThread->Info = Thread->Info; - NewThread->Registers = Thread->Registers; + memcpy(NewThread->FPU, Thread->FPU, sizeof(CPU::x64::FXState)); + NewThread->Stack->Fork(Thread->Stack); + NewThread->Info = Thread->Info; + NewThread->Registers = Thread->Registers; - if (Thread->Security.IsCritical) - NewThread->SetCritical(true); - TaskManager->GetSecurityManager()->TrustToken(NewProcess->Security.UniqueToken, - (Tasking::TTL)TaskManager->GetSecurityManager()->GetTokenTrustLevel(Parent->Security.UniqueToken)); - TaskManager->GetSecurityManager()->TrustToken(NewThread->Security.UniqueToken, - (Tasking::TTL)TaskManager->GetSecurityManager()->GetTokenTrustLevel(Thread->Security.UniqueToken)); + if (Thread->Security.IsCritical) + NewThread->SetCritical(true); + TaskManager->GetSecurityManager()->TrustToken(NewProcess->Security.UniqueToken, + (Tasking::TTL)TaskManager->GetSecurityManager()->GetTokenTrustLevel(Parent->Security.UniqueToken)); + TaskManager->GetSecurityManager()->TrustToken(NewThread->Security.UniqueToken, + (Tasking::TTL)TaskManager->GetSecurityManager()->GetTokenTrustLevel(Thread->Security.UniqueToken)); #ifdef a86 - NewThread->ShadowGSBase = Thread->ShadowGSBase; - NewThread->GSBase = Thread->GSBase; - NewThread->FSBase = Thread->FSBase; + NewThread->ShadowGSBase = Thread->ShadowGSBase; + NewThread->GSBase = Thread->GSBase; + NewThread->FSBase = Thread->FSBase; #endif - debug("Forked thread \"%s\"(%d) to \"%s\"(%d)", Thread->Name, Thread->ID, NewThread->Name, NewThread->ID); - NewThread->Status = Tasking::TaskStatus::Ready; - return (int)NewThread->ID; + debug("Forked thread \"%s\"(%d) to \"%s\"(%d)", Thread->Name, Thread->ID, NewThread->Name, NewThread->ID); + NewThread->Status = Tasking::TaskStatus::Ready; + return (int)NewThread->ID; + UNUSED(Frame); } static int sys_wait(SyscallsFrame *Frame) { - fixme("sys_wait: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_wait: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_kill(SyscallsFrame *Frame) { - fixme("sys_kill: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_kill: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_spawn(SyscallsFrame *Frame) { - fixme("sys_spawn: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_spawn: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_spawn_thread(SyscallsFrame *Frame, uint64_t InstructionPointer) { - Tasking::TCB *thread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)InstructionPointer); - if (thread) - return (int)thread->ID; - return SYSCALL_ERROR; + Tasking::TCB *thread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)InstructionPointer); + if (thread) + return (int)thread->ID; + return SYSCALL_ERROR; } static int sys_get_thread_list_of_process(SyscallsFrame *Frame) { - fixme("sys_get_thread_list_of_process: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_get_thread_list_of_process: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_get_current_process(SyscallsFrame *Frame) { - fixme("sys_get_current_process: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_get_current_process: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_get_current_thread(SyscallsFrame *Frame) { - fixme("sys_get_current_thread: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_get_current_thread: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_get_current_process_id(SyscallsFrame *Frame) { - return (int)TaskManager->GetCurrentProcess()->ID; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; + + return (int)TaskManager->GetCurrentProcess()->ID; } static int sys_get_current_thread_id(SyscallsFrame *Frame) { - return (int)TaskManager->GetCurrentThread()->ID; + if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) + return SYSCALL_ACCESS_DENIED; + + return (int)TaskManager->GetCurrentThread()->ID; } static int sys_get_process_by_pid(SyscallsFrame *Frame) { - fixme("sys_get_process_by_pid: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_get_process_by_pid: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_get_thread_by_tid(SyscallsFrame *Frame) { - fixme("sys_get_thread_by_tid: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_get_thread_by_tid: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_kill_process(SyscallsFrame *Frame) { - fixme("sys_kill_process: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_kill_process: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_kill_thread(SyscallsFrame *Frame) { - fixme("sys_kill_thread: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_kill_thread: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_sys_reserved_create_process(SyscallsFrame *Frame) { - fixme("sys_sys_reserved_create_process: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_sys_reserved_create_process: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } static int sys_sys_reserved_create_thread(SyscallsFrame *Frame) { - fixme("sys_sys_reserved_create_thread: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; + fixme("sys_sys_reserved_create_thread: %#lx", Frame); + return SYSCALL_NOT_IMPLEMENTED; } -static void *NativeSyscallsTable[] = { - [_Exit] = (void *)sys_exit, - [_Print] = (void *)sys_print, +static void *NativeSyscallsTable[_MaxSyscall] = { + [_Exit] = (void *)sys_exit, + [_Print] = (void *)sys_print, - [_RequestPages] = (void *)sys_request_pages, - [_FreePages] = (void *)sys_free_pages, - [_DetachAddress] = (void *)sys_detach_address, + [_RequestPages] = (void *)sys_request_pages, + [_FreePages] = (void *)sys_free_pages, + [_DetachAddress] = (void *)sys_detach_address, + [_MemoryMap] = (void *)sys_memory_map, + [_MemoryUnmap] = (void *)sys_memory_unmap, - [_KernelCTL] = (void *)sys_kernelctl, - [_IPC] = (void *)sys_ipc, + [_KernelCTL] = (void *)sys_kernelctl, - [_FileOpen] = (void *)sys_file_open, - [_FileClose] = (void *)sys_file_close, - [_FileRead] = (void *)sys_file_read, - [_FileWrite] = (void *)sys_file_write, - [_FileSeek] = (void *)sys_file_seek, - [_FileStatus] = (void *)sys_file_status, + [_FileOpen] = (void *)sys_file_open, + [_FileClose] = (void *)sys_file_close, + [_FileRead] = (void *)sys_file_read, + [_FileWrite] = (void *)sys_file_write, + [_FileSeek] = (void *)sys_file_seek, + [_FileStatus] = (void *)sys_file_status, - [_Sleep] = (void *)sys_sleep, - [_Fork] = (void *)sys_fork, - [_Wait] = (void *)sys_wait, - [_Kill] = (void *)sys_kill, - [_Spawn] = (void *)sys_spawn, - [_SpawnThread] = (void *)sys_spawn_thread, - [_GetThreadListOfProcess] = (void *)sys_get_thread_list_of_process, - [_GetCurrentProcess] = (void *)sys_get_current_process, - [_GetCurrentThread] = (void *)sys_get_current_thread, - [_GetCurrentProcessID] = (void *)sys_get_current_process_id, - [_GetCurrentThreadID] = (void *)sys_get_current_thread_id, - [_GetProcessByPID] = (void *)sys_get_process_by_pid, - [_GetThreadByTID] = (void *)sys_get_thread_by_tid, - [_KillProcess] = (void *)sys_kill_process, - [_KillThread] = (void *)sys_kill_thread, - [_SysReservedCreateProcess] = (void *)sys_sys_reserved_create_process, - [_SysReservedCreateThread] = (void *)sys_sys_reserved_create_thread, + [_IPC] = (void *)sys_ipc, + [_Sleep] = (void *)sys_sleep, + [_Fork] = (void *)sys_fork, + [_Wait] = (void *)sys_wait, + [_Kill] = (void *)sys_kill, + [_Spawn] = (void *)sys_spawn, + [_SpawnThread] = (void *)sys_spawn_thread, + [_GetThreadListOfProcess] = (void *)sys_get_thread_list_of_process, + [_GetCurrentProcess] = (void *)sys_get_current_process, + [_GetCurrentThread] = (void *)sys_get_current_thread, + [_GetCurrentProcessID] = (void *)sys_get_current_process_id, + [_GetCurrentThreadID] = (void *)sys_get_current_thread_id, + [_GetProcessByPID] = (void *)sys_get_process_by_pid, + [_GetThreadByTID] = (void *)sys_get_thread_by_tid, + [_KillProcess] = (void *)sys_kill_process, + [_KillThread] = (void *)sys_kill_thread, + [_SysReservedCreateProcess] = (void *)sys_sys_reserved_create_process, + [_SysReservedCreateThread] = (void *)sys_sys_reserved_create_thread, }; uintptr_t HandleNativeSyscalls(SyscallsFrame *Frame) { #if defined(a64) - if (Frame->rax > sizeof(NativeSyscallsTable)) - { - fixme("Syscall %ld not implemented", Frame->rax); - return SYSCALL_NOT_IMPLEMENTED; - } + if (Frame->rax > sizeof(NativeSyscallsTable)) + { + fixme("Syscall %ld not implemented", Frame->rax); + return SYSCALL_NOT_IMPLEMENTED; + } - uintptr_t (*call)(uintptr_t, ...) = reinterpret_cast(NativeSyscallsTable[Frame->rax]); - if (!call) - { - error("Syscall %#lx failed.", Frame->rax); - return SYSCALL_INTERNAL_ERROR; - } + uintptr_t (*call)(uintptr_t, ...) = reinterpret_cast(NativeSyscallsTable[Frame->rax]); + if (!call) + { + error("Syscall %#lx failed.", Frame->rax); + return SYSCALL_INTERNAL_ERROR; + } - // debug("[%#lx]->( %#lx %#lx %#lx %#lx %#lx %#lx )", - // Frame->rax, - // Frame->rdi, Frame->rsi, Frame->rdx, Frame->rcx, Frame->r8, Frame->r9); + debug("[%#lx]->( %#lx %#lx %#lx %#lx %#lx %#lx )", + Frame->rax, + Frame->rdi, Frame->rsi, Frame->rdx, Frame->rcx, Frame->r8, Frame->r9); - uintptr_t ret = call((uintptr_t)Frame, Frame->rdi, Frame->rsi, Frame->rdx, Frame->r10, Frame->r8, Frame->r9); - Frame->rax = ret; - return ret; + uintptr_t ret = call((uintptr_t)Frame, Frame->rdi, Frame->rsi, Frame->rdx, Frame->r10, Frame->r8, Frame->r9); + Frame->rax = ret; + return ret; #elif defined(a32) - if (Frame->eax > sizeof(NativeSyscallsTable)) - { - fixme("Syscall %ld not implemented", Frame->eax); - return SYSCALL_NOT_IMPLEMENTED; - } + if (Frame->eax > sizeof(NativeSyscallsTable)) + { + fixme("Syscall %ld not implemented", Frame->eax); + return SYSCALL_NOT_IMPLEMENTED; + } - /* ... */ + /* ... */ - return SYSCALL_INTERNAL_ERROR; + return SYSCALL_INTERNAL_ERROR; #elif defined(aa64) - return SYSCALL_INTERNAL_ERROR; + return SYSCALL_INTERNAL_ERROR; #endif } diff --git a/SystemCalls/Syscalls.cpp b/SystemCalls/Syscalls.cpp index 069d642..c27eea3 100644 --- a/SystemCalls/Syscalls.cpp +++ b/SystemCalls/Syscalls.cpp @@ -55,7 +55,7 @@ extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame) default: { error("Unknown compatibility mode! Killing thread..."); - TaskManager->KillThread(TaskManager->GetCurrentThread(), -0xCA11); + TaskManager->KillThread(TaskManager->GetCurrentThread(), Tasking::KILL_SYSCALL); break; } } diff --git a/Tasking/Scheduler.cpp b/Tasking/Scheduler.cpp index 8e776cb..8ba140d 100644 --- a/Tasking/Scheduler.cpp +++ b/Tasking/Scheduler.cpp @@ -56,8 +56,8 @@ NewLock(SchedulerLock); #define DEBUG_WAKE_UP_THREADS 1 #define schedbg(m, ...) \ - debug(m, ##__VA_ARGS__); \ - __sync + debug(m, ##__VA_ARGS__); \ + __sync #else #define schedbg(m, ...) #endif @@ -65,8 +65,8 @@ NewLock(SchedulerLock); /* GetNextAvailableThread */ #ifdef DEBUG_GET_NEXT_AVAILABLE_PROCESS #define gnap_schedbg(m, ...) \ - debug(m, ##__VA_ARGS__); \ - __sync + debug(m, ##__VA_ARGS__); \ + __sync #else #define gnap_schedbg(m, ...) #endif @@ -74,8 +74,8 @@ NewLock(SchedulerLock); /* GetNextAvailableProcess */ #ifdef DEBUG_GET_NEXT_AVAILABLE_THREAD #define gnat_schedbg(m, ...) \ - debug(m, ##__VA_ARGS__); \ - __sync + debug(m, ##__VA_ARGS__); \ + __sync #else #define gnat_schedbg(m, ...) #endif @@ -83,8 +83,8 @@ NewLock(SchedulerLock); /* FindNewProcess */ #ifdef DEBUG_FIND_NEW_PROCESS #define fnp_schedbg(m, ...) \ - debug(m, ##__VA_ARGS__); \ - __sync + debug(m, ##__VA_ARGS__); \ + __sync #else #define fnp_schedbg(m, ...) #endif @@ -92,8 +92,8 @@ NewLock(SchedulerLock); /* SchedulerSearchProcessThread */ #ifdef DEBUG_SCHEDULER_SEARCH_PROCESS_THREAD #define sspt_schedbg(m, ...) \ - debug(m, ##__VA_ARGS__); \ - __sync + debug(m, ##__VA_ARGS__); \ + __sync #else #define sspt_schedbg(m, ...) #endif @@ -101,18 +101,18 @@ NewLock(SchedulerLock); /* WakeUpThreads */ #ifdef DEBUG_WAKE_UP_THREADS #define wut_schedbg(m, ...) \ - debug(m, ##__VA_ARGS__); \ - __sync + debug(m, ##__VA_ARGS__); \ + __sync #else #define wut_schedbg(m, ...) #endif extern "C" SafeFunction NIF void TaskingScheduler_OneShot(int TimeSlice) { - if (TimeSlice == 0) - TimeSlice = Tasking::TaskPriority::Normal; + if (TimeSlice == 0) + TimeSlice = Tasking::TaskPriority::Normal; #if defined(a64) - ((APIC::Timer *)Interrupts::apicTimer[GetCurrentCPU()->ID])->OneShot(CPU::x86::IRQ16, TimeSlice); + ((APIC::Timer *)Interrupts::apicTimer[GetCurrentCPU()->ID])->OneShot(CPU::x86::IRQ16, TimeSlice); #elif defined(a32) #elif defined(aa64) #endif @@ -121,614 +121,613 @@ extern "C" SafeFunction NIF void TaskingScheduler_OneShot(int TimeSlice) namespace Tasking { #if defined(a64) - SafeFunction NIF bool Task::FindNewProcess(void *CPUDataPointer) - { - CPUData *CurrentCPU = (CPUData *)CPUDataPointer; - fnp_schedbg("%d processes", ProcessList.size()); + SafeFunction NIF bool Task::FindNewProcess(void *CPUDataPointer) + { + CPUData *CurrentCPU = (CPUData *)CPUDataPointer; + fnp_schedbg("%d processes", ProcessList.size()); #ifdef DEBUG_FIND_NEW_PROCESS - foreach (auto process in ProcessList) - fnp_schedbg("Process %d %s", process->ID, process->Name); + foreach (auto process in ProcessList) + fnp_schedbg("Process %d %s", process->ID, process->Name); #endif - foreach (auto process in ProcessList) - { - if (InvalidPCB(process)) - continue; + foreach (auto process in ProcessList) + { + if (InvalidPCB(process)) + continue; - switch (process->Status) - { - case TaskStatus::Ready: - fnp_schedbg("Ready process (%s)%d", - process->Name, process->ID); - break; - default: - fnp_schedbg("Process \"%s\"(%d) status %d", - process->Name, process->ID, - process->Status); + switch (process->Status) + { + case TaskStatus::Ready: + fnp_schedbg("Ready process (%s)%d", + process->Name, process->ID); + break; + default: + fnp_schedbg("Process \"%s\"(%d) status %d", + process->Name, process->ID, + process->Status); - /* We don't actually remove the process. RemoveProcess - firstly checks if it's terminated, if not, it will - loop through Threads and call RemoveThread on - terminated threads. */ - RemoveProcess(process); - continue; - } + /* We don't actually remove the process. RemoveProcess + firstly checks if it's terminated, if not, it will + loop through Threads and call RemoveThread on + terminated threads. */ + RemoveProcess(process); + continue; + } - foreach (auto thread in process->Threads) - { - if (InvalidTCB(thread)) - continue; + foreach (auto thread in process->Threads) + { + if (InvalidTCB(thread)) + continue; - if (thread->Status != TaskStatus::Ready) - continue; + if (thread->Status != TaskStatus::Ready) + continue; - if (thread->Info.Affinity[CurrentCPU->ID] == false) - continue; + if (thread->Info.Affinity[CurrentCPU->ID] == false) + continue; - CurrentCPU->CurrentProcess = process; - CurrentCPU->CurrentThread = thread; - return true; - } - } - fnp_schedbg("No process to run."); - return false; - } + CurrentCPU->CurrentProcess = process; + CurrentCPU->CurrentThread = thread; + return true; + } + } + fnp_schedbg("No process to run."); + return false; + } - SafeFunction NIF bool Task::GetNextAvailableThread(void *CPUDataPointer) - { - CPUData *CurrentCPU = (CPUData *)CPUDataPointer; + SafeFunction NIF bool Task::GetNextAvailableThread(void *CPUDataPointer) + { + CPUData *CurrentCPU = (CPUData *)CPUDataPointer; - for (size_t i = 0; i < CurrentCPU->CurrentProcess->Threads.size(); i++) - { - if (CurrentCPU->CurrentProcess->Threads[i] == CurrentCPU->CurrentThread.load()) - { - size_t TempIndex = i; - RetryAnotherThread: - TCB *nextThread = CurrentCPU->CurrentProcess->Threads[TempIndex + 1]; + for (size_t i = 0; i < CurrentCPU->CurrentProcess->Threads.size(); i++) + { + if (CurrentCPU->CurrentProcess->Threads[i] == CurrentCPU->CurrentThread.load()) + { + size_t TempIndex = i; + RetryAnotherThread: + TCB *nextThread = CurrentCPU->CurrentProcess->Threads[TempIndex + 1]; - if (unlikely(InvalidTCB(nextThread))) - { - if (TempIndex > CurrentCPU->CurrentProcess->Threads.size()) - break; - TempIndex++; + if (unlikely(InvalidTCB(nextThread))) + { + if (TempIndex > CurrentCPU->CurrentProcess->Threads.size()) + break; + TempIndex++; - gnat_schedbg("Thread %#lx is invalid", nextThread); - goto RetryAnotherThread; - } + gnat_schedbg("Thread %#lx is invalid", nextThread); + goto RetryAnotherThread; + } - gnat_schedbg("\"%s\"(%d) and next thread is \"%s\"(%d)", - CurrentCPU->CurrentProcess->Threads[i]->Name, - CurrentCPU->CurrentProcess->Threads[i]->ID, - thread->Name, thread->ID); + gnat_schedbg("\"%s\"(%d) and next thread is \"%s\"(%d)", + CurrentCPU->CurrentProcess->Threads[i]->Name, + CurrentCPU->CurrentProcess->Threads[i]->ID, + nextThread->Name, nextThread->ID); - if (nextThread->Status != TaskStatus::Ready) - { - gnat_schedbg("Thread %d is not ready", nextThread->ID); - TempIndex++; - goto RetryAnotherThread; - } + if (nextThread->Status != TaskStatus::Ready) + { + gnat_schedbg("Thread %d is not ready", nextThread->ID); + TempIndex++; + goto RetryAnotherThread; + } - if (nextThread->Info.Affinity[CurrentCPU->ID] == false) - continue; + if (nextThread->Info.Affinity[CurrentCPU->ID] == false) + continue; - CurrentCPU->CurrentThread = nextThread; - gnat_schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d", - thread->ID, thread->Parent->Name, - CurrentCPU->CurrentProcess->Threads.size(), ProcessList.size()); - return true; - } + CurrentCPU->CurrentThread = nextThread; + gnat_schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d", + nextThread->ID, nextThread->Parent->Name, + CurrentCPU->CurrentProcess->Threads.size(), ProcessList.size()); + return true; + } #ifdef DEBUG - else - { - gnat_schedbg("Thread %d is not the current one", - CurrentCPU->CurrentProcess->Threads[i]->ID); - } + else + { + gnat_schedbg("Thread %d is not the current one", + CurrentCPU->CurrentProcess->Threads[i]->ID); + } #endif - } - return false; - } + } + return false; + } - SafeFunction NIF bool Task::GetNextAvailableProcess(void *CPUDataPointer) - { - CPUData *CurrentCPU = (CPUData *)CPUDataPointer; + SafeFunction NIF bool Task::GetNextAvailableProcess(void *CPUDataPointer) + { + CPUData *CurrentCPU = (CPUData *)CPUDataPointer; - bool Skip = true; - foreach (auto process in ProcessList) - { - if (process == CurrentCPU->CurrentProcess.load()) - { - Skip = false; - gnap_schedbg("Found current process %#lx", process); - continue; - } + bool Skip = true; + foreach (auto process in ProcessList) + { + if (process == CurrentCPU->CurrentProcess.load()) + { + Skip = false; + gnap_schedbg("Found current process %#lx", process); + continue; + } - if (Skip) - { - gnap_schedbg("Skipping process %#lx", process); - continue; - } + if (Skip) + { + gnap_schedbg("Skipping process %#lx", process); + continue; + } - if (InvalidPCB(process)) - { - gnap_schedbg("Invalid process %#lx", process); - continue; - } + if (InvalidPCB(process)) + { + gnap_schedbg("Invalid process %#lx", process); + continue; + } - if (process->Status != TaskStatus::Ready) - { - gnap_schedbg("Process %d is not ready", process->ID); - continue; - } + if (process->Status != TaskStatus::Ready) + { + gnap_schedbg("Process %d is not ready", process->ID); + continue; + } - foreach (auto thread in process->Threads) - { - if (InvalidTCB(thread)) - { - gnap_schedbg("Invalid thread %#lx", thread); - continue; - } + foreach (auto thread in process->Threads) + { + if (InvalidTCB(thread)) + { + gnap_schedbg("Invalid thread %#lx", thread); + continue; + } - if (thread->Status != TaskStatus::Ready) - { - gnap_schedbg("Thread %d is not ready", thread->ID); - continue; - } + if (thread->Status != TaskStatus::Ready) + { + gnap_schedbg("Thread %d is not ready", thread->ID); + continue; + } - if (thread->Info.Affinity[CurrentCPU->ID] == false) - continue; + if (thread->Info.Affinity[CurrentCPU->ID] == false) + continue; - CurrentCPU->CurrentProcess = process; - CurrentCPU->CurrentThread = thread; - gnap_schedbg("[cur proc+1 -> first thd] Scheduling thread %d %s->%d (Total Procs %d)", - thread->ID, thread->Name, process->Threads.size(), ProcessList.size()); - return true; - } - } - gnap_schedbg("No process to run."); - return false; - } + CurrentCPU->CurrentProcess = process; + CurrentCPU->CurrentThread = thread; + gnap_schedbg("[cur proc+1 -> first thd] Scheduling thread %d %s->%d (Total Procs %d)", + thread->ID, thread->Name, process->Threads.size(), ProcessList.size()); + return true; + } + } + gnap_schedbg("No process to run."); + return false; + } - SafeFunction NIF bool Task::SchedulerSearchProcessThread(void *CPUDataPointer) - { - CPUData *CurrentCPU = (CPUData *)CPUDataPointer; + SafeFunction NIF bool Task::SchedulerSearchProcessThread(void *CPUDataPointer) + { + CPUData *CurrentCPU = (CPUData *)CPUDataPointer; - foreach (auto process in ProcessList) - { - if (InvalidPCB(process)) - { - sspt_schedbg("Invalid process %#lx", process); - continue; - } + foreach (auto process in ProcessList) + { + if (InvalidPCB(process)) + { + sspt_schedbg("Invalid process %#lx", process); + continue; + } - if (process->Status != TaskStatus::Ready) - { - sspt_schedbg("Process %d is not ready", process->ID); - continue; - } + if (process->Status != TaskStatus::Ready) + { + sspt_schedbg("Process %d is not ready", process->ID); + continue; + } - foreach (auto thread in process->Threads) - { - if (InvalidTCB(thread)) - { - sspt_schedbg("Invalid thread %#lx", thread); - continue; - } + foreach (auto thread in process->Threads) + { + if (InvalidTCB(thread)) + { + sspt_schedbg("Invalid thread %#lx", thread); + continue; + } - if (thread->Status != TaskStatus::Ready) - { - sspt_schedbg("Thread %d is not ready", thread->ID); - continue; - } + if (thread->Status != TaskStatus::Ready) + { + sspt_schedbg("Thread %d is not ready", thread->ID); + continue; + } - if (thread->Info.Affinity[CurrentCPU->ID] == false) - continue; + if (thread->Info.Affinity[CurrentCPU->ID] == false) + continue; - CurrentCPU->CurrentProcess = process; - CurrentCPU->CurrentThread = thread; - sspt_schedbg("[proc 0 -> end -> first thd] Scheduling thread %d parent of %s->%d (Procs %d)", - thread->ID, thread->Parent->Name, process->Threads.size(), ProcessList.size()); - return true; - } - } - return false; - } + CurrentCPU->CurrentProcess = process; + CurrentCPU->CurrentThread = thread; + sspt_schedbg("[proc 0 -> end -> first thd] Scheduling thread %d parent of %s->%d (Procs %d)", + thread->ID, thread->Parent->Name, process->Threads.size(), ProcessList.size()); + return true; + } + } + return false; + } - SafeFunction NIF void Task::UpdateProcessStatus() - { - foreach (auto process in ProcessList) - { - if (InvalidPCB(process)) - continue; + SafeFunction NIF void Task::UpdateProcessStatus() + { + foreach (auto process in ProcessList) + { + if (InvalidPCB(process)) + continue; - if (process->Status == TaskStatus::Terminated || - process->Status == TaskStatus::Stopped) - continue; + if (process->Status == TaskStatus::Terminated || + process->Status == TaskStatus::Stopped) + continue; - bool AllThreadsSleeping = true; - foreach (auto thread in process->Threads) - { - if (thread->Status != TaskStatus::Sleeping) - { - AllThreadsSleeping = false; - break; - } - } + bool AllThreadsSleeping = true; + foreach (auto thread in process->Threads) + { + if (thread->Status != TaskStatus::Sleeping) + { + AllThreadsSleeping = false; + break; + } + } - if (AllThreadsSleeping) - process->Status = TaskStatus::Sleeping; - else if (process->Status == TaskStatus::Sleeping) - process->Status = TaskStatus::Ready; - } - } + if (AllThreadsSleeping) + process->Status = TaskStatus::Sleeping; + else if (process->Status == TaskStatus::Sleeping) + process->Status = TaskStatus::Ready; + } + } - SafeFunction NIF void Task::WakeUpThreads() - { - foreach (auto process in ProcessList) - { - if (InvalidPCB(process)) - continue; + SafeFunction NIF void Task::WakeUpThreads() + { + foreach (auto process in ProcessList) + { + if (InvalidPCB(process)) + continue; - if (process->Status == TaskStatus::Terminated || - process->Status == TaskStatus::Stopped) - continue; + if (process->Status == TaskStatus::Terminated || + process->Status == TaskStatus::Stopped) + continue; - foreach (auto thread in process->Threads) - { - if (InvalidTCB(thread)) - continue; + foreach (auto thread in process->Threads) + { + if (InvalidTCB(thread)) + continue; - if (thread->Status != TaskStatus::Sleeping) - continue; + if (thread->Status != TaskStatus::Sleeping) + continue; - /* Check if the thread is ready to wake up. */ - if (thread->Info.SleepUntil < TimeManager->GetCounter()) - { - if (process->Status == TaskStatus::Sleeping) - process->Status = TaskStatus::Ready; - thread->Status = TaskStatus::Ready; + /* Check if the thread is ready to wake up. */ + if (thread->Info.SleepUntil < TimeManager->GetCounter()) + { + if (process->Status == TaskStatus::Sleeping) + process->Status = TaskStatus::Ready; + thread->Status = TaskStatus::Ready; - thread->Info.SleepUntil = 0; - wut_schedbg("Thread \"%s\"(%d) woke up.", thread->Name, thread->ID); - } - else - { - wut_schedbg("Thread \"%s\"(%d) is not ready to wake up. (SleepUntil: %d, Counter: %d)", - thread->Name, thread->ID, thread->Info.SleepUntil, TimeManager->GetCounter()); - } - } - } - } + thread->Info.SleepUntil = 0; + wut_schedbg("Thread \"%s\"(%d) woke up.", thread->Name, thread->ID); + } + else + { + wut_schedbg("Thread \"%s\"(%d) is not ready to wake up. (SleepUntil: %d, Counter: %d)", + thread->Name, thread->ID, thread->Info.SleepUntil, TimeManager->GetCounter()); + } + } + } + } #ifdef ON_SCREEN_SCHEDULER_TASK_MANAGER - int SuccessSource = 0; - int sanity; + int SuccessSource = 0; + int sanity; - const char *Statuses[] = { - "FF0000", /* Unknown */ - "AAFF00", /* Ready */ - "00AA00", /* Running */ - "FFAA00", /* Sleeping */ - "FFAA00", /* Waiting */ - "FF0088", /* Stopped */ - "FF0000", /* Terminated */ - }; + const char *Statuses[] = { + "FF0000", /* Unknown */ + "AAFF00", /* Ready */ + "00AA00", /* Running */ + "FFAA00", /* Sleeping */ + "FFAA00", /* Waiting */ + "FF0088", /* Stopped */ + "FF0000", /* Terminated */ + }; - const char *StatusesSign[] = { - "Unknown", - "Ready", - "Run", - "Sleep", - "Wait", - "Stop", - "Terminated", - }; + const char *StatusesSign[] = { + "Unknown", + "Ready", + "Run", + "Sleep", + "Wait", + "Stop", + "Terminated", + }; - const char *SuccessSourceStrings[] = { - "Unknown", - "GetNextAvailableThread", - "GetNextAvailableProcess", - "SchedulerSearchProcessThread", - }; + const char *SuccessSourceStrings[] = { + "Unknown", + "GetNextAvailableThread", + "GetNextAvailableProcess", + "SchedulerSearchProcessThread", + }; - SafeFunction NIF void OnScreenTaskManagerUpdate() - { - TimeManager->Sleep(100); - Video::ScreenBuffer *sb = Display->GetBuffer(0); - for (short i = 0; i < 340; i++) - { - for (short j = 0; j < 200; j++) - { - uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo->Framebuffer[0].BitsPerPixel / 8)); - *Pixel = 0x222222; - } - } + SafeFunction NIF void OnScreenTaskManagerUpdate() + { + TimeManager->Sleep(10, Time::Units::Milliseconds); + Video::ScreenBuffer *sb = Display->GetBuffer(0); + for (short i = 0; i < 340; i++) + { + for (short j = 0; j < 600; j++) + { + uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo.Framebuffer[0].BitsPerPixel / 8)); + *Pixel = 0x222222; + } + } - uint32_t tmpX, tmpY; - Display->GetBufferCursor(0, &tmpX, &tmpY); - Display->SetBufferCursor(0, 0, 0); - printf("\eF02C21Task Manager\n"); - foreach (auto Proc in TaskManager->GetProcessList()) - { - int Status = Proc->Status; - printf("\e%s-> \eAABBCC%s \e00AAAA%s\n", - Statuses[Status], Proc->Name, StatusesSign[Status]); + uint32_t tmpX, tmpY; + Display->GetBufferCursor(0, &tmpX, &tmpY); + Display->SetBufferCursor(0, 0, 0); + printf("\eF02C21Task Manager\n"); + foreach (auto Proc in TaskManager->GetProcessList()) + { + int Status = Proc->Status; + printf("\e%s-> \eAABBCC%s \e00AAAA%s\n", + Statuses[Status], Proc->Name, StatusesSign[Status]); - foreach (auto Thd in Proc->Threads) - { - Status = Thd->Status; - printf(" \e%s-> \eAABBCC%s \e00AAAA%s\n\eAABBCC", - Statuses[Status], Thd->Name, StatusesSign[Status]); - } - } - register uintptr_t CurrentStackAddress asm("rsp"); - printf("Sanity: %d, Stack: %#lx\nSched. Source: %s", sanity++, CurrentStackAddress, SuccessSourceStrings[SuccessSource]); - if (sanity > 1000) - sanity = 0; - Display->SetBufferCursor(0, tmpX, tmpY); - Display->SetBuffer(0); - TimeManager->Sleep(100); - } + foreach (auto Thd in Proc->Threads) + { + Status = Thd->Status; + printf(" \e%s-> \eAABBCC%s \e00AAAA%s\n\eAABBCC", + Statuses[Status], Thd->Name, StatusesSign[Status]); + } + } + register uintptr_t CurrentStackAddress asm("rsp"); + printf("Sanity: %d, Stack: %#lx\nSched. Source: %s", sanity++, CurrentStackAddress, SuccessSourceStrings[SuccessSource]); + if (sanity > 1000) + sanity = 0; + Display->SetBufferCursor(0, tmpX, tmpY); + Display->SetBuffer(0); + TimeManager->Sleep(10, Time::Units::Milliseconds); + } #endif - SafeFunction NIF void Task::Schedule(CPU::x64::TrapFrame *Frame) - { - if (StopScheduler) - { - warn("Scheduler stopped."); - return; - } - bool ProcessNotChanged = false; - CPU::x64::writecr3({.raw = (uint64_t)KernelPageTable}); /* Restore kernel page table for safety reasons. */ - uint64_t SchedTmpTicks = TimeManager->GetCounter(); - this->LastTaskTicks.store(SchedTmpTicks - this->SchedulerTicks.load()); - CPUData *CurrentCPU = GetCurrentCPU(); - this->LastCore.store(CurrentCPU->ID); - schedbg("Scheduler called on CPU %d.", CurrentCPU->ID); - schedbg("%d: %ld%%", CurrentCPU->ID, GetUsage(CurrentCPU->ID)); + SafeFunction NIF void Task::Schedule(CPU::x64::TrapFrame *Frame) + { + if (StopScheduler) + { + warn("Scheduler stopped."); + return; + } + bool ProcessNotChanged = false; + CPU::x64::writecr3({.raw = (uint64_t)KernelPageTable}); /* Restore kernel page table for safety reasons. */ + uint64_t SchedTmpTicks = TimeManager->GetCounter(); + this->LastTaskTicks.store(SchedTmpTicks - this->SchedulerTicks.load()); + CPUData *CurrentCPU = GetCurrentCPU(); + this->LastCore.store(CurrentCPU->ID); + schedbg("Scheduler called on CPU %d.", CurrentCPU->ID); #ifdef DEBUG_SCHEDULER - { - schedbg("================================================================"); - schedbg("Status: 0-ukn | 1-rdy | 2-run | 3-wait | 4-term"); - schedbg("Technical Informations on regs %#lx", Frame->InterruptNumber); - size_t ds; - asmv("mov %%ds, %0" - : "=r"(ds)); - schedbg("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx", - CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), - Frame->ss, Frame->cs, ds); - schedbg("R8=%#lx R9=%#lx R10=%#lx R11=%#lx", - Frame->r8, Frame->r9, Frame->r10, Frame->r11); - schedbg("R12=%#lx R13=%#lx R14=%#lx R15=%#lx", - Frame->r12, Frame->r13, Frame->r14, Frame->r15); - schedbg("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx", - Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); - schedbg("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx", - Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); - schedbg("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx", - Frame->rip, Frame->rflags, Frame->InterruptNumber, Frame->ErrorCode); - schedbg("================================================================"); - } + { + schedbg("================================================================"); + schedbg("Status: 0-ukn | 1-rdy | 2-run | 3-wait | 4-term"); + schedbg("Technical Informations on regs %#lx", Frame->InterruptNumber); + size_t ds; + asmv("mov %%ds, %0" + : "=r"(ds)); + schedbg("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx", + CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), + Frame->ss, Frame->cs, ds); + schedbg("R8=%#lx R9=%#lx R10=%#lx R11=%#lx", + Frame->r8, Frame->r9, Frame->r10, Frame->r11); + schedbg("R12=%#lx R13=%#lx R14=%#lx R15=%#lx", + Frame->r12, Frame->r13, Frame->r14, Frame->r15); + schedbg("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx", + Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); + schedbg("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx", + Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); + schedbg("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx", + Frame->rip, Frame->rflags, Frame->InterruptNumber, Frame->ErrorCode); + schedbg("================================================================"); + } #endif - if (unlikely(InvalidPCB(CurrentCPU->CurrentProcess.load()) || InvalidTCB(CurrentCPU->CurrentThread.load()))) - { - schedbg("Invalid process or thread. Finding a new one."); - ProcessNotChanged = true; - if (this->FindNewProcess(CurrentCPU)) - goto Success; - else - goto Idle; - } - else - { - CurrentCPU->CurrentThread->Registers = *Frame; - CPU::x64::fxsave(CurrentCPU->CurrentThread->FPU); - CurrentCPU->CurrentThread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSR_SHADOW_GS_BASE); - CurrentCPU->CurrentThread->GSBase = CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE); - CurrentCPU->CurrentThread->FSBase = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE); + if (unlikely(InvalidPCB(CurrentCPU->CurrentProcess.load()) || InvalidTCB(CurrentCPU->CurrentThread.load()))) + { + schedbg("Invalid process or thread. Finding a new one."); + ProcessNotChanged = true; + if (this->FindNewProcess(CurrentCPU)) + goto Success; + else + goto Idle; + } + else + { + CurrentCPU->CurrentThread->Registers = *Frame; + CPU::x64::fxsave(CurrentCPU->CurrentThread->FPU); + CurrentCPU->CurrentThread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSR_SHADOW_GS_BASE); + CurrentCPU->CurrentThread->GSBase = CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE); + CurrentCPU->CurrentThread->FSBase = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE); - if (CurrentCPU->CurrentProcess->Status == TaskStatus::Running) - CurrentCPU->CurrentProcess->Status = TaskStatus::Ready; - if (CurrentCPU->CurrentThread->Status == TaskStatus::Running) - CurrentCPU->CurrentThread->Status = TaskStatus::Ready; + if (CurrentCPU->CurrentProcess->Status == TaskStatus::Running) + CurrentCPU->CurrentProcess->Status = TaskStatus::Ready; + if (CurrentCPU->CurrentThread->Status == TaskStatus::Running) + CurrentCPU->CurrentThread->Status = TaskStatus::Ready; - this->UpdateProcessStatus(); - schedbg("Passed UpdateProcessStatus"); + this->UpdateProcessStatus(); + schedbg("Passed UpdateProcessStatus"); - this->WakeUpThreads(); - schedbg("Passed WakeUpThreads"); + this->WakeUpThreads(); + schedbg("Passed WakeUpThreads"); - if (this->GetNextAvailableThread(CurrentCPU)) - { + if (this->GetNextAvailableThread(CurrentCPU)) + { #ifdef ON_SCREEN_SCHEDULER_TASK_MANAGER - SuccessSource = 1; + SuccessSource = 1; #endif - ProcessNotChanged = true; - goto Success; - } - schedbg("Passed GetNextAvailableThread"); + ProcessNotChanged = true; + goto Success; + } + schedbg("Passed GetNextAvailableThread"); - if (this->GetNextAvailableProcess(CurrentCPU)) - { + if (this->GetNextAvailableProcess(CurrentCPU)) + { #ifdef ON_SCREEN_SCHEDULER_TASK_MANAGER - SuccessSource = 2; + SuccessSource = 2; #endif - goto Success; - } - schedbg("Passed GetNextAvailableProcess"); + goto Success; + } + schedbg("Passed GetNextAvailableProcess"); - if (SchedulerSearchProcessThread(CurrentCPU)) - { + if (SchedulerSearchProcessThread(CurrentCPU)) + { #ifdef ON_SCREEN_SCHEDULER_TASK_MANAGER - SuccessSource = 3; + SuccessSource = 3; #endif - schedbg("Passed SchedulerSearchProcessThread"); - goto Success; - } - else - { - schedbg("SchedulerSearchProcessThread failed. Going idle."); - goto Idle; - } - } + schedbg("Passed SchedulerSearchProcessThread"); + goto Success; + } + else + { + schedbg("SchedulerSearchProcessThread failed. Going idle."); + goto Idle; + } + } - warn("Unwanted reach!"); - TaskingScheduler_OneShot(100); - goto End; + warn("Unwanted reach!"); + TaskingScheduler_OneShot(100); + goto End; - Idle: - ProcessNotChanged = true; - CurrentCPU->CurrentProcess = IdleProcess; - CurrentCPU->CurrentThread = IdleThread; + Idle: + ProcessNotChanged = true; + CurrentCPU->CurrentProcess = IdleProcess; + CurrentCPU->CurrentThread = IdleThread; - Success: - schedbg("Process \"%s\"(%d) Thread \"%s\"(%d) is now running on CPU %d", - CurrentCPU->CurrentProcess->Name, CurrentCPU->CurrentProcess->ID, - CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID, CurrentCPU->ID); + Success: + schedbg("Process \"%s\"(%d) Thread \"%s\"(%d) is now running on CPU %d", + CurrentCPU->CurrentProcess->Name, CurrentCPU->CurrentProcess->ID, + CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID, CurrentCPU->ID); - if (!ProcessNotChanged) - UpdateUsage(&CurrentCPU->CurrentProcess->Info, &CurrentCPU->CurrentProcess->Security, CurrentCPU->ID); - UpdateUsage(&CurrentCPU->CurrentThread->Info, &CurrentCPU->CurrentThread->Security, CurrentCPU->ID); + if (!ProcessNotChanged) + UpdateUsage(&CurrentCPU->CurrentProcess->Info, &CurrentCPU->CurrentProcess->Security, CurrentCPU->ID); + UpdateUsage(&CurrentCPU->CurrentThread->Info, &CurrentCPU->CurrentThread->Security, CurrentCPU->ID); - CurrentCPU->CurrentProcess->Status = TaskStatus::Running; - CurrentCPU->CurrentThread->Status = TaskStatus::Running; + CurrentCPU->CurrentProcess->Status = TaskStatus::Running; + CurrentCPU->CurrentThread->Status = TaskStatus::Running; - *Frame = CurrentCPU->CurrentThread->Registers; + *Frame = CurrentCPU->CurrentThread->Registers; - for (size_t i = 0; i < sizeof(CurrentCPU->CurrentThread->IPHistory) / sizeof(CurrentCPU->CurrentThread->IPHistory[0]); i++) - CurrentCPU->CurrentThread->IPHistory[i + 1] = CurrentCPU->CurrentThread->IPHistory[i]; + for (size_t i = 0; i < (sizeof(CurrentCPU->CurrentThread->IPHistory) / sizeof(CurrentCPU->CurrentThread->IPHistory[0])) - 1; i++) + CurrentCPU->CurrentThread->IPHistory[i + 1] = CurrentCPU->CurrentThread->IPHistory[i]; - CurrentCPU->CurrentThread->IPHistory[0] = Frame->rip; + CurrentCPU->CurrentThread->IPHistory[0] = Frame->rip; - GlobalDescriptorTable::SetKernelStack((void *)((uintptr_t)CurrentCPU->CurrentThread->Stack->GetStackTop())); - CPU::x64::writecr3({.raw = (uint64_t)CurrentCPU->CurrentProcess->PageTable}); - /* Not sure if this is needed, but it's better to be safe than sorry. */ - asmv("movq %cr3, %rax"); - asmv("movq %rax, %cr3"); - CPU::x64::fxrstor(CurrentCPU->CurrentThread->FPU); - CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->ShadowGSBase); - CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, CurrentCPU->CurrentThread->GSBase); - CPU::x64::wrmsr(CPU::x64::MSR_FS_BASE, CurrentCPU->CurrentThread->FSBase); + GlobalDescriptorTable::SetKernelStack((void *)((uintptr_t)CurrentCPU->CurrentThread->Stack->GetStackTop())); + CPU::x64::writecr3({.raw = (uint64_t)CurrentCPU->CurrentProcess->PageTable}); + /* Not sure if this is needed, but it's better to be safe than sorry. */ + asmv("movq %cr3, %rax"); + asmv("movq %rax, %cr3"); + CPU::x64::fxrstor(CurrentCPU->CurrentThread->FPU); + CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->ShadowGSBase); + CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, CurrentCPU->CurrentThread->GSBase); + CPU::x64::wrmsr(CPU::x64::MSR_FS_BASE, CurrentCPU->CurrentThread->FSBase); #ifdef ON_SCREEN_SCHEDULER_TASK_MANAGER - OnScreenTaskManagerUpdate(); + OnScreenTaskManagerUpdate(); #endif - switch (CurrentCPU->CurrentProcess->Security.TrustLevel) - { - case TaskTrustLevel::System: - case TaskTrustLevel::Kernel: - // wrmsr(MSR_SHADOW_GS_BASE, (uint64_t)CurrentCPU->CurrentThread); - break; - case TaskTrustLevel::User: - // wrmsr(MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->gs); - break; - default: - error("Unknown trust level %d.", - CurrentCPU->CurrentProcess->Security.TrustLevel); - break; - } + switch (CurrentCPU->CurrentProcess->Security.TrustLevel) + { + case TaskTrustLevel::System: + case TaskTrustLevel::Kernel: + // wrmsr(MSR_SHADOW_GS_BASE, (uint64_t)CurrentCPU->CurrentThread); + break; + case TaskTrustLevel::User: + // wrmsr(MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->gs); + break; + default: + error("Unknown trust level %d.", + CurrentCPU->CurrentProcess->Security.TrustLevel); + break; + } - if (!ProcessNotChanged) - (&CurrentCPU->CurrentProcess->Info)->LastUpdateTime = TimeManager->GetCounter(); - (&CurrentCPU->CurrentThread->Info)->LastUpdateTime = TimeManager->GetCounter(); - TaskingScheduler_OneShot(CurrentCPU->CurrentThread->Info.Priority); + if (!ProcessNotChanged) + (&CurrentCPU->CurrentProcess->Info)->LastUpdateTime = TimeManager->GetCounter(); + (&CurrentCPU->CurrentThread->Info)->LastUpdateTime = TimeManager->GetCounter(); + TaskingScheduler_OneShot(CurrentCPU->CurrentThread->Info.Priority); - if (CurrentCPU->CurrentThread->Security.IsDebugEnabled && CurrentCPU->CurrentThread->Security.IsKernelDebugEnabled) - trace("%s[%ld]: RIP=%#lx RBP=%#lx RSP=%#lx", - CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID, - CurrentCPU->CurrentThread->Registers.rip, - CurrentCPU->CurrentThread->Registers.rbp, - CurrentCPU->CurrentThread->Registers.rsp); + if (CurrentCPU->CurrentThread->Security.IsDebugEnabled && CurrentCPU->CurrentThread->Security.IsKernelDebugEnabled) + trace("%s[%ld]: RIP=%#lx RBP=%#lx RSP=%#lx", + CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID, + CurrentCPU->CurrentThread->Registers.rip, + CurrentCPU->CurrentThread->Registers.rbp, + CurrentCPU->CurrentThread->Registers.rsp); - schedbg("================================================================"); - schedbg("Technical Informations on Thread %s[%ld]:", - CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID); - uint64_t ds; - asmv("mov %%ds, %0" - : "=r"(ds)); - schedbg("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx", - CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), - Frame->ss, Frame->cs, ds); - schedbg("R8=%#lx R9=%#lx R10=%#lx R11=%#lx", - Frame->r8, Frame->r9, Frame->r10, Frame->r11); - schedbg("R12=%#lx R13=%#lx R14=%#lx R15=%#lx", - Frame->r12, Frame->r13, Frame->r14, Frame->r15); - schedbg("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx", - Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); - schedbg("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx", - Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); - schedbg("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx", - Frame->rip, Frame->rflags, Frame->InterruptNumber, Frame->ErrorCode); - schedbg("================================================================"); + schedbg("================================================================"); + schedbg("Technical Informations on Thread %s[%ld]:", + CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID); + uint64_t ds; + asmv("mov %%ds, %0" + : "=r"(ds)); + schedbg("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx", + CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), + Frame->ss, Frame->cs, ds); + schedbg("R8=%#lx R9=%#lx R10=%#lx R11=%#lx", + Frame->r8, Frame->r9, Frame->r10, Frame->r11); + schedbg("R12=%#lx R13=%#lx R14=%#lx R15=%#lx", + Frame->r12, Frame->r13, Frame->r14, Frame->r15); + schedbg("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx", + Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); + schedbg("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx", + Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); + schedbg("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx", + Frame->rip, Frame->rflags, Frame->InterruptNumber, Frame->ErrorCode); + schedbg("================================================================"); - End: - this->SchedulerTicks.store(TimeManager->GetCounter() - SchedTmpTicks); - __sync; /* TODO: Is this really needed? */ - } + End: + this->SchedulerTicks.store(TimeManager->GetCounter() - SchedTmpTicks); + __sync; /* TODO: Is this really needed? */ + } - SafeFunction NIF void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame) - { - SmartCriticalSection(SchedulerLock); - this->Schedule(Frame); - } + SafeFunction NIF void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame) + { + SmartCriticalSection(SchedulerLock); + this->Schedule(Frame); + } #elif defined(a32) - SafeFunction bool Task::FindNewProcess(void *CPUDataPointer) - { - fixme("unimplemented"); - return false; - } + SafeFunction bool Task::FindNewProcess(void *CPUDataPointer) + { + fixme("unimplemented"); + return false; + } - SafeFunction bool Task::GetNextAvailableThread(void *CPUDataPointer) - { - fixme("unimplemented"); - return false; - } + SafeFunction bool Task::GetNextAvailableThread(void *CPUDataPointer) + { + fixme("unimplemented"); + return false; + } - SafeFunction bool Task::GetNextAvailableProcess(void *CPUDataPointer) - { - fixme("unimplemented"); - return false; - } + SafeFunction bool Task::GetNextAvailableProcess(void *CPUDataPointer) + { + fixme("unimplemented"); + return false; + } - SafeFunction bool Task::SchedulerSearchProcessThread(void *CPUDataPointer) - { - fixme("unimplemented"); - return false; - } + SafeFunction bool Task::SchedulerSearchProcessThread(void *CPUDataPointer) + { + fixme("unimplemented"); + return false; + } - SafeFunction void Task::Schedule(void *Frame) - { - fixme("unimplemented"); - } + SafeFunction void Task::Schedule(void *Frame) + { + fixme("unimplemented"); + } - SafeFunction void Task::OnInterruptReceived(CPU::x32::TrapFrame *Frame) { this->Schedule(Frame); } + SafeFunction void Task::OnInterruptReceived(CPU::x32::TrapFrame *Frame) { this->Schedule(Frame); } #elif defined(aa64) - SafeFunction bool Task::FindNewProcess(void *CPUDataPointer) - { - fixme("unimplemented"); - } + SafeFunction bool Task::FindNewProcess(void *CPUDataPointer) + { + fixme("unimplemented"); + } - SafeFunction bool Task::GetNextAvailableThread(void *CPUDataPointer) - { - fixme("unimplemented"); - } + SafeFunction bool Task::GetNextAvailableThread(void *CPUDataPointer) + { + fixme("unimplemented"); + } - SafeFunction bool Task::GetNextAvailableProcess(void *CPUDataPointer) - { - fixme("unimplemented"); - } + SafeFunction bool Task::GetNextAvailableProcess(void *CPUDataPointer) + { + fixme("unimplemented"); + } - SafeFunction bool Task::SchedulerSearchProcessThread(void *CPUDataPointer) - { - fixme("unimplemented"); - } + SafeFunction bool Task::SchedulerSearchProcessThread(void *CPUDataPointer) + { + fixme("unimplemented"); + } - SafeFunction void Task::Schedule(CPU::aarch64::TrapFrame *Frame) - { - fixme("unimplemented"); - } + SafeFunction void Task::Schedule(CPU::aarch64::TrapFrame *Frame) + { + fixme("unimplemented"); + } - SafeFunction void Task::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame) { this->Schedule(Frame); } + SafeFunction void Task::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame) { this->Schedule(Frame); } #endif } diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index 2cef53b..27a1eee 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -187,7 +187,7 @@ namespace Tasking PCB *Task::GetCurrentProcess() { return GetCurrentCPU()->CurrentProcess.load(); } TCB *Task::GetCurrentThread() { return GetCurrentCPU()->CurrentThread.load(); } - PCB *Task::GetProcessByID(UPID ID) + PCB *Task::GetProcessByID(TID ID) { for (size_t i = 0; i < ProcessList.size(); i++) if (ProcessList[i]->ID == ID) @@ -195,7 +195,7 @@ namespace Tasking return nullptr; } - TCB *Task::GetThreadByID(UTID ID) + TCB *Task::GetThreadByID(TID ID) { for (size_t i = 0; i < ProcessList.size(); i++) for (size_t j = 0; j < ProcessList[i]->Threads.size(); j++) @@ -257,14 +257,8 @@ namespace Tasking thread->Parent->Status = TaskStatus::Sleeping; thread->Info.SleepUntil = TimeManager->CalculateTarget(Milliseconds, Time::Units::Milliseconds); tskdbg("Thread \"%s\"(%d) is going to sleep until %llu", thread->Name, thread->ID, thread->Info.SleepUntil); - // TaskingScheduler_OneShot(1); - // IRQ16 TaskingLock.Unlock(); -#if defined(a86) - asmv("int $0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */ -#elif defined(aa64) - asmv("svc #0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */ -#endif + this->Schedule(); } void Task::SignalShutdown() @@ -313,7 +307,7 @@ namespace Tasking delete Process->ELFSymbolTable, Process->ELFSymbolTable = nullptr; delete Process, Process = nullptr; ProcessList.remove(i); - NextPID--; + this->NextPID--; break; } } @@ -334,18 +328,17 @@ namespace Tasking delete Thread->Memory, Thread->Memory = nullptr; SecurityManager.DestroyToken(Thread->Security.UniqueToken); delete Thread, Thread = nullptr; - NextTID--; + this->NextTID--; } __no_sanitize("undefined") TCB *Task::CreateThread(PCB *Parent, - IP EntryPoint, - const char **argv, - const char **envp, - const std::vector &auxv, - IPOffset Offset, - TaskArchitecture Architecture, - TaskCompatibility Compatibility, - bool ThreadNotReady) + IP EntryPoint, + const char **argv, + const char **envp, + const std::vector &auxv, + TaskArchitecture Architecture, + TaskCompatibility Compatibility, + bool ThreadNotReady) { SmartLock(TaskingLock); TCB *Thread = new TCB; @@ -372,7 +365,6 @@ namespace Tasking Thread->ID = this->NextTID++; strcpy(Thread->Name, Parent->Name); Thread->EntryPoint = EntryPoint; - Thread->Offset = Offset; Thread->ExitCode = 0xdead; if (ThreadNotReady) Thread->Status = TaskStatus::Waiting; @@ -405,7 +397,7 @@ namespace Tasking #if defined(a64) memset(&Thread->Registers, 0, sizeof(CPU::x64::TrapFrame)); // Just in case - Thread->Registers.rip = (EntryPoint + Offset); + Thread->Registers.rip = EntryPoint; #elif defined(a32) #elif defined(aa64) #endif @@ -440,7 +432,7 @@ namespace Tasking Thread->Stack = new Memory::StackGuard(true, Parent->PageTable); #if defined(a64) SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::Untrusted); - Thread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE); + Thread->ShadowGSBase = (uint64_t)GetCurrentCPU(); Thread->GSBase = 0; Thread->FSBase = 0; Thread->Registers.cs = GDT_USER_CODE; @@ -625,13 +617,13 @@ namespace Tasking #ifdef DEBUG #ifdef a64 - debug("Thread offset is %#lx (EntryPoint: %#lx) => RIP: %#lx", Thread->Offset, Thread->EntryPoint, Thread->Registers.rip); + debug("Thread EntryPoint: %#lx => RIP: %#lx", Thread->EntryPoint, Thread->Registers.rip); if (Parent->Security.TrustLevel == TaskTrustLevel::User) debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.rsp); else debug("Thread stack region is %#lx-%#lx (K) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.rsp); #elif defined(a32) - debug("Thread offset is %#lx (EntryPoint: %#lx) => RIP: %#lx", Thread->Offset, Thread->EntryPoint, Thread->Registers.eip); + debug("Thread EntryPoint: %#lx => RIP: %#lx", Thread->EntryPoint, Thread->Registers.eip); if (Parent->Security.TrustLevel == TaskTrustLevel::User) debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.esp); else @@ -654,7 +646,7 @@ namespace Tasking { SmartLock(TaskingLock); PCB *Process = new PCB; - Process->ID = this->NextPID++; + Process->ID = NextPID++; strcpy(Process->Name, Name); if (Parent == nullptr) Process->Parent = this->GetCurrentProcess(); @@ -667,7 +659,7 @@ namespace Tasking Process->Security.UniqueToken = SecurityManager.CreateToken(); char ProcFSName[16]; - sprintf(ProcFSName, "%ld", Process->ID); + sprintf(ProcFSName, "%d", Process->ID); Process->ProcessDirectory = vfs->Create(ProcFSName, VirtualFileSystem::NodeFlags::DIRECTORY, ProcFS); Process->memDirectory = vfs->Create("mem", VirtualFileSystem::NodeFlags::DIRECTORY, Process->ProcessDirectory); Process->IPC = new InterProcessCommunication::IPC((void *)Process); @@ -706,7 +698,7 @@ namespace Tasking default: { error("Unknown elevation."); - this->NextPID--; + NextPID--; delete Process; return nullptr; } @@ -767,9 +759,10 @@ namespace Tasking #elif defined(aa64) TaskArchitecture Arch = TaskArchitecture::ARM64; #endif + PCB *kproc = CreateProcess(nullptr, "Kernel", TaskTrustLevel::Kernel); kproc->ELFSymbolTable = KernelSymbolTable; - TCB *kthrd = CreateThread(kproc, EntryPoint, nullptr, nullptr, std::vector(), 0, Arch); + TCB *kthrd = CreateThread(kproc, EntryPoint, nullptr, nullptr, std::vector(), Arch); kthrd->Rename("Main Thread"); debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name); TaskingLock.Lock(__FUNCTION__); @@ -843,12 +836,12 @@ namespace Tasking if (Thread == GetCurrentCPU()->CurrentThread.load() || Thread == CleanupThread) continue; - this->KillThread(Thread, 0xFFFF); + this->KillThread(Thread, KILL_SCHEDULER_DESTRUCTION); } if (Process == GetCurrentCPU()->CurrentProcess.load()) continue; - this->KillProcess(Process, 0xFFFF); + this->KillProcess(Process, KILL_SCHEDULER_DESTRUCTION); } } diff --git a/Tests/Marco.cpp b/Tests/Marco.cpp index 7b3ea81..138dc65 100644 --- a/Tests/Marco.cpp +++ b/Tests/Marco.cpp @@ -112,14 +112,14 @@ __constructor void TestMacros() result = ROUND_UP(x, y); if (result != 0x200) { - error("ERROR: ROUND_UP failed: %d != 0x200\n", result); + error("ERROR: ROUND_UP failed: %d != 0x200", result); inf_loop; } result = ROUND_DOWN(x, y); if (result != 0x100) { - error("ERROR: ROUND_DOWN failed: %d != 0x100\n", result); + error("ERROR: ROUND_DOWN failed: %d != 0x100", result); inf_loop; } } diff --git a/Tests/MemoryAllocation.cpp b/Tests/MemoryAllocation.cpp index 1810a42..12ff434 100644 --- a/Tests/MemoryAllocation.cpp +++ b/Tests/MemoryAllocation.cpp @@ -178,7 +178,7 @@ void TestMemoryAllocation() uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); kfree((void *)prq2); - debug(" Result:\t1-[%#lx]; 2-[%#lx]\n", (void *)prq1, (void *)prq2); + debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); assert(prq1 == prq2); } diff --git a/include/cpu.hpp b/include/cpu.hpp index 160534f..a56c174 100644 --- a/include/cpu.hpp +++ b/include/cpu.hpp @@ -289,45 +289,82 @@ namespace CPU uint32_t ss; // Stack Segment } TrapFrame; - // ! TODO: UNTESTED! + typedef union DR6 + { + struct + { + /** @brief Breakpoint #0 Condition Detected */ + uint64_t B0 : 1; + /** @brief Breakpoint #1 Condition Detected */ + uint64_t B1 : 1; + /** @brief Breakpoint #2 Condition Detected */ + uint64_t B2 : 1; + /** @brief Breakpoint #3 Condition Detected */ + uint64_t B3 : 1; + /** @brief Reserved */ + uint64_t Reserved0 : 8; + /** @brief Reserved */ + uint64_t Reserved1 : 1; + /** @brief Breakpoint Debug Access Detected */ + uint64_t BD : 1; + /** @brief Breakpoint Single Step */ + uint64_t BS : 1; + /** @brief Breakpoint Task Switch */ + uint64_t BT : 1; + /** @brief Reserved */ + uint64_t Reserved2 : 15; + }; + uint64_t raw; + } DR6; + typedef union DR7 { struct { - /** @brief Local DR0 Breakpoint (0) */ - uint32_t LocalDR0 : 1; - /** @brief Global DR0 Breakpoint (1) */ - uint32_t GlobalDR0 : 1; - /** @brief Local DR1 Breakpoint (2) */ - uint32_t LocalDR1 : 1; - /** @brief Global DR1 Breakpoint (3) */ - uint32_t GlobalDR1 : 1; - /** @brief Local DR2 Breakpoint (4) */ - uint32_t LocalDR2 : 1; - /** @brief Global DR2 Breakpoint (5) */ - uint32_t GlobalDR2 : 1; - /** @brief Local DR3 Breakpoint (6) */ - uint32_t LocalDR3 : 1; - /** @brief Global DR3 Breakpoint (7) */ - uint32_t GlobalDR3 : 1; - /** @brief Reserved [7 - (16-17)] */ - uint32_t Reserved : 9; - /** @brief Conditions for DR0 (16-17) */ - uint32_t ConditionsDR0 : 1; - /** @brief Size of DR0 Breakpoint (18-19) */ - uint32_t SizeDR0 : 1; - /** @brief Conditions for DR1 (20-21) */ - uint32_t ConditionsDR1 : 1; - /** @brief Size of DR1 Breakpoint (22-23) */ - uint32_t SizeDR1 : 1; - /** @brief Conditions for DR2 (24-25) */ - uint32_t ConditionsDR2 : 1; - /** @brief Size of DR2 Breakpoint (26-27) */ - uint32_t SizeDR2 : 1; - /** @brief Conditions for DR3 (28-29) */ - uint32_t ConditionsDR3 : 1; - /** @brief Size of DR3 Breakpoint (30-31) */ - uint32_t SizeDR3 : 1; + /** @brief Local Exact Breakpoint #0 Enabled */ + uint32_t L0 : 1; + /** @brief Global Exact Breakpoint #0 Enabled */ + uint32_t G0 : 1; + /** @brief Local Exact Breakpoint #1 Enabled */ + uint32_t L1 : 1; + /** @brief Global Exact Breakpoint #1 Enabled */ + uint32_t G1 : 1; + /** @brief Local Exact Breakpoint #2 Enabled */ + uint32_t L2 : 1; + /** @brief Global Exact Breakpoint #2 Enabled */ + uint32_t G2 : 1; + /** @brief Local Exact Breakpoint #3 Enabled */ + uint32_t L3 : 1; + /** @brief Global Exact Breakpoint #3 Enabled */ + uint32_t G3 : 1; + /** @brief Local Exact Breakpoint Enabled */ + uint32_t LE : 1; + /** @brief Global Exact Breakpoint Enabled */ + uint32_t GE : 1; + /** @brief Reserved */ + uint32_t Reserved0 : 1; + /** @brief Reserved */ + uint32_t Reserved1 : 2; + /** @brief General Detect Enabled */ + uint32_t GD : 1; + /** @brief Reserved */ + uint32_t Reserved2 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint32_t RW0 : 2; + /** @brief Length of Breakpoint #0 */ + uint32_t LEN0 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint32_t RW1 : 2; + /** @brief Length of Breakpoint #1 */ + uint32_t LEN1 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint32_t RW2 : 2; + /** @brief Length of Breakpoint #2 */ + uint32_t LEN2 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint32_t RW3 : 2; + /** @brief Length of Breakpoint #3 */ + uint32_t LEN3 : 2; }; uint32_t raw; } DR7; @@ -590,45 +627,86 @@ namespace CPU uint64_t raw; } __packed EFER; - // ! TODO: UNTESTED! + typedef union DR6 + { + struct + { + /** @brief Breakpoint #0 Condition Detected */ + uint64_t B0 : 1; + /** @brief Breakpoint #1 Condition Detected */ + uint64_t B1 : 1; + /** @brief Breakpoint #2 Condition Detected */ + uint64_t B2 : 1; + /** @brief Breakpoint #3 Condition Detected */ + uint64_t B3 : 1; + /** @brief Reserved */ + uint64_t Reserved0 : 8; + /** @brief Reserved */ + uint64_t Reserved1 : 1; + /** @brief Breakpoint Debug Access Detected */ + uint64_t BD : 1; + /** @brief Breakpoint Single Step */ + uint64_t BS : 1; + /** @brief Breakpoint Task Switch */ + uint64_t BT : 1; + /** @brief Reserved */ + uint64_t Reserved2 : 15; + /** @brief Reserved */ + uint64_t Reserved3 : 32; + }; + uint64_t raw; + } DR6; + typedef union DR7 { struct { - /** @brief Local DR0 Breakpoint (0) */ - uint64_t LocalDR0 : 1; - /** @brief Global DR0 Breakpoint (1) */ - uint64_t GlobalDR0 : 1; - /** @brief Local DR1 Breakpoint (2) */ - uint64_t LocalDR1 : 1; - /** @brief Global DR1 Breakpoint (3) */ - uint64_t GlobalDR1 : 1; - /** @brief Local DR2 Breakpoint (4) */ - uint64_t LocalDR2 : 1; - /** @brief Global DR2 Breakpoint (5) */ - uint64_t GlobalDR2 : 1; - /** @brief Local DR3 Breakpoint (6) */ - uint64_t LocalDR3 : 1; - /** @brief Global DR3 Breakpoint (7) */ - uint64_t GlobalDR3 : 1; - /** @brief Reserved [7 - (16-17)] */ - uint64_t Reserved : 9; - /** @brief Conditions for DR0 (16-17) */ - uint64_t ConditionsDR0 : 1; - /** @brief Size of DR0 Breakpoint (18-19) */ - uint64_t SizeDR0 : 1; - /** @brief Conditions for DR1 (20-21) */ - uint64_t ConditionsDR1 : 1; - /** @brief Size of DR1 Breakpoint (22-23) */ - uint64_t SizeDR1 : 1; - /** @brief Conditions for DR2 (24-25) */ - uint64_t ConditionsDR2 : 1; - /** @brief Size of DR2 Breakpoint (26-27) */ - uint64_t SizeDR2 : 1; - /** @brief Conditions for DR3 (28-29) */ - uint64_t ConditionsDR3 : 1; - /** @brief Size of DR3 Breakpoint (30-31) */ - uint64_t SizeDR3 : 1; + /** @brief Local Exact Breakpoint #0 Enabled */ + uint64_t L0 : 1; + /** @brief Global Exact Breakpoint #0 Enabled */ + uint64_t G0 : 1; + /** @brief Local Exact Breakpoint #1 Enabled */ + uint64_t L1 : 1; + /** @brief Global Exact Breakpoint #1 Enabled */ + uint64_t G1 : 1; + /** @brief Local Exact Breakpoint #2 Enabled */ + uint64_t L2 : 1; + /** @brief Global Exact Breakpoint #2 Enabled */ + uint64_t G2 : 1; + /** @brief Local Exact Breakpoint #3 Enabled */ + uint64_t L3 : 1; + /** @brief Global Exact Breakpoint #3 Enabled */ + uint64_t G3 : 1; + /** @brief Local Exact Breakpoint Enabled */ + uint64_t LE : 1; + /** @brief Global Exact Breakpoint Enabled */ + uint64_t GE : 1; + /** @brief Reserved */ + uint64_t Reserved0 : 1; + /** @brief Reserved */ + uint64_t Reserved1 : 2; + /** @brief General Detect Enabled */ + uint64_t GD : 1; + /** @brief Reserved */ + uint64_t Reserved2 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint64_t RW0 : 2; + /** @brief Length of Breakpoint #0 */ + uint64_t LEN0 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint64_t RW1 : 2; + /** @brief Length of Breakpoint #1 */ + uint64_t LEN1 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint64_t RW2 : 2; + /** @brief Length of Breakpoint #2 */ + uint64_t LEN2 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint64_t RW3 : 2; + /** @brief Length of Breakpoint #3 */ + uint64_t LEN3 : 2; + /** @brief Reserved */ + uint64_t Reserved3 : 32; }; uint64_t raw; } DR7; diff --git a/include/debug.h b/include/debug.h index fb14f65..da8b0f4 100644 --- a/include/debug.h +++ b/include/debug.h @@ -23,13 +23,15 @@ enum DebugLevel { DebugLevelNone = 0, - DebugLevelError = 1, - DebugLevelWarning = 2, - DebugLevelInfo = 3, - DebugLevelDebug = 4, - DebugLevelTrace = 5, - DebugLevelFixme = 6, - DebugLevelUbsan = 7 + DebugLevelError, + DebugLevelWarning, + DebugLevelInfo, + DebugLevelDebug, + DebugLevelTrace, + DebugLevelFixme, + DebugLevelUbsan, + DebugLevelStub, + DebugLevelFunction, }; #ifdef __cplusplus @@ -48,12 +50,15 @@ namespace SysDbg #ifdef DEBUG #define debug(Format, ...) SysDbg::WriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #define ubsan(Format, ...) SysDbg::WriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) +#define function(Format, ...) SysDbg::WriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #else #define debug(Format, ...) #define ubsan(Format, ...) +#define function(Format, ...) #endif #define trace(Format, ...) SysDbg::WriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #define fixme(Format, ...) SysDbg::WriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) +#define stub SysDbg::WriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub") #define locked_error(Format, ...) SysDbg::LockedWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #define locked_warn(Format, ...) SysDbg::LockedWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) @@ -61,12 +66,15 @@ namespace SysDbg #ifdef DEBUG #define locked_debug(Format, ...) SysDbg::LockedWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #define locked_ubsan(Format, ...) SysDbg::LockedWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) +#define locked_function(Format, ...) SysDbg::LockedWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #else #define locked_debug(Format, ...) #define locked_ubsan(Format, ...) +#define locked_function(Format, ...) #endif #define locked_trace(Format, ...) SysDbg::LockedWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #define locked_fixme(Format, ...) SysDbg::LockedWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) +#define locked_stub SysDbg::LockedWriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub") #else @@ -81,12 +89,15 @@ void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, co #ifdef DEBUG #define debug(Format, ...) SysDbgWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #define ubsan(Format, ...) SysDbgWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) +#define function(Format, ...) SysDbgWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #else #define debug(Format, ...) #define ubsan(Format, ...) +#define function(Format, ...) #endif #define trace(Format, ...) SysDbgWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #define fixme(Format, ...) SysDbgWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) +#define stub SysDbgWriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub") #define locked_error(Format, ...) SysDbgLockedWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #define locked_warn(Format, ...) SysDbgLockedWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) @@ -94,15 +105,16 @@ void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, co #ifdef DEBUG #define locked_debug(Format, ...) SysDbgLockedWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #define locked_ubsan(Format, ...) SysDbgLockedWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) +#define locked_function(Format, ...) SysDbgLockedWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #else #define locked_debug(Format, ...) #define locked_ubsan(Format, ...) +#define locked_function(Format, ...) #endif #define locked_trace(Format, ...) SysDbgLockedWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) #define locked_fixme(Format, ...) SysDbgLockedWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__) +#define locked_stub SysDbgLockedWriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub") #endif // __cplusplus -#define stub fixme("stub") - #endif // !__FENNIX_KERNEL_DEBUGGER_H__ diff --git a/include/elf.h b/include/elf.h index 0451c68..1886dc3 100644 --- a/include/elf.h +++ b/include/elf.h @@ -20,9 +20,6 @@ #include -// https://wiki.osdev.org/ELF_Tutorial -// https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h - /* 32-bit ELF base types. */ typedef uint32_t Elf32_Addr; typedef uint16_t Elf32_Half; @@ -40,365 +37,275 @@ typedef uint32_t Elf64_Word; typedef uint64_t Elf64_Xword; typedef int64_t Elf64_Sxword; -#define EI_NIDENT 16 - -typedef struct elf32_hdr +enum IdentificationIndex { - unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; /* Entry point virtual address */ - Elf32_Off e_phoff; /* Program header table file offset */ - Elf32_Off e_shoff; /* Section header table file offset */ - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -typedef struct elf64_hdr -{ - unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; -} Elf64_Ehdr; - -typedef struct elf32_shdr -{ - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -typedef struct elf64_shdr -{ - Elf64_Word sh_name; /* Section name, index in string tbl */ - Elf64_Word sh_type; /* Type of section */ - Elf64_Xword sh_flags; /* Miscellaneous section attributes */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Size of section in bytes */ - Elf64_Word sh_link; /* Index of another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -} Elf64_Shdr; - -typedef struct -{ - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} Elf32_Phdr; - -typedef struct -{ - Elf64_Word p_type; - Elf64_Word p_flags; - Elf64_Off p_offset; - Elf64_Addr p_vaddr; - Elf64_Addr p_paddr; - Elf64_Xword p_filesz; - Elf64_Xword p_memsz; - Elf64_Xword p_align; -} Elf64_Phdr; - -typedef struct elf32_rel -{ - Elf32_Addr r_offset; - Elf32_Word r_info; -} Elf32_Rel; - -typedef struct elf64_rel -{ - Elf64_Addr r_offset; /* Location at which to apply the action */ - Elf64_Xword r_info; /* index and type of relocation */ -} Elf64_Rel; - -typedef struct elf32_sym -{ - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf32_Half st_shndx; -} Elf32_Sym; - -typedef struct elf64_sym -{ - Elf64_Word st_name; /* Symbol name, index in string tbl */ - unsigned char st_info; /* Type and binding attributes */ - unsigned char st_other; /* No defined meaning, 0 */ - Elf64_Half st_shndx; /* Associated section index */ - Elf64_Addr st_value; /* Value of the symbol */ - Elf64_Xword st_size; /* Associated symbol size */ -} Elf64_Sym; - -struct Elf32_Dyn -{ - Elf32_Sword d_tag; /* Type of dynamic table entry. */ - union - { - Elf32_Word d_val; /* Integer value of entry. */ - Elf32_Addr d_ptr; /* Pointer value of entry. */ - } d_un; -}; - -struct Elf64_Dyn -{ - Elf64_Sxword d_tag; /* Type of dynamic table entry. */ - union - { - Elf64_Xword d_val; /* Integer value of entry. */ - Elf64_Addr d_ptr; /* Pointer value of entry. */ - } d_un; -}; - -typedef struct -{ - Elf64_Addr r_offset; - Elf64_Xword r_info; - Elf64_Sxword r_addend; -} Elf64_Rela; - -enum Elf_Ident -{ - EI_MAG0 = 0, // 0x7F - EI_MAG1 = 1, // 'E' - EI_MAG2 = 2, // 'L' - EI_MAG3 = 3, // 'F' - EI_CLASS = 4, // Architecture (32/64) - EI_DATA = 5, // Byte Order - EI_VERSION = 6, // ELF Version - EI_OSABI = 7, // OS Specific - EI_ABIVERSION = 8, // OS Specific - EI_PAD = 9 // Padding + EI_MAG0 = 0, + EI_MAG1 = 1, + EI_MAG2 = 2, + EI_MAG3 = 3, + EI_CLASS = 4, + EI_DATA = 5, + EI_VERSION = 6, + EI_OSABI = 7, + EI_ABIVERSION = 8, + EI_PAD = 9, + EI_NIDENT = 16 }; enum Elf_OSABI { - ELFOSABI_NONE = 0, - ELFOSABI_HPUX = 1, - ELFOSABI_NETBSD = 2, - ELFOSABI_LINUX = 3, - ELFOSABI_HURD = 4, - ELFOSABI_SOLARIS = 6, - ELFOSABI_AIX = 7, - ELFOSABI_IRIX = 8, - ELFOSABI_FREEBSD = 9, - ELFOSABI_TRU64 = 10, - ELFOSABI_MODESTO = 11, - ELFOSABI_OPENBSD = 12, - ELFOSABI_OPENVMS = 13, - ELFOSABI_NSK = 14, - ELFOSABI_AROS = 15, - ELFOSABI_FENIXOS = 16, - ELFOSABI_CLOUDABI = 17, - ELFOSABI_OPENVOS = 18, - ELFOSABI_C6000_ELFABI = 64, - ELFOSABI_C6000_LINUX = 65, - ELFOSABI_ARM = 97, - ELFOSABI_STANDALONE = 255 + ELFOSABI_NONE = 0, + ELFOSABI_SYSV = 0, + ELFOSABI_HPUX = 1, + ELFOSABI_NETBSD = 2, + ELFOSABI_GNU = 3, + ELFOSABI_LINUX = 3, + ELFOSABI_HURD = 4, + ELFOSABI_SOLARIS = 6, + ELFOSABI_AIX = 7, + ELFOSABI_IRIX = 8, + ELFOSABI_FREEBSD = 9, + ELFOSABI_TRU64 = 10, + ELFOSABI_MODESTO = 11, + ELFOSABI_OPENBSD = 12, + ELFOSABI_OPENVMS = 13, + ELFOSABI_NSK = 14, + ELFOSABI_AROS = 15, + ELFOSABI_FENIXOS = 16, + ELFOSABI_CLOUDABI = 17, + ELFOSABI_OPENVOS = 18, + ELFOSABI_C6000_ELFABI = 64, + ELFOSABI_C6000_LINUX = 65, + ELFOSABI_ARM = 97, + ELFOSABI_STANDALONE = 255 }; -enum Elf_Type +enum FileIdentifiers { - ET_NONE = 0, // Unknown Type - ET_REL = 1, // Relocatable File - ET_EXEC = 2, // Executable File - ET_DYN = 3, // Shared Object File - ET_CORE = 4, // Core File - ET_LOPROC = 0xff00, // Processor Specific - ET_HIPROC = 0xffff // Processor Specific + ET_NONE = 0, + ET_REL = 1, + ET_EXEC = 2, + ET_DYN = 3, + ET_CORE = 4, + ET_LOPROC = 0xff00, + ET_HIPROC = 0xffff }; -enum RtT_Types +enum RelocationTypes { - R_386_NONE = 0, // No relocation - R_386_32 = 1, // Symbol + Offset - R_386_PC32 = 2, // Symbol + Offset - Section Offset + R_386_NONE = 0, + R_386_32 = 1, + R_386_PC32 = 2, + R_386_GOT32 = 3, + R_386_PLT32 = 4, + R_386_COPY = 5, + R_386_GLOB_DAT = 6, + R_386_JMP_SLOT = 7, + R_386_RELATIVE = 8, + R_386_GOTOFF = 9, + R_386_GOTPC = 10, + R_386_32PLT = 11, + R_386_TLS_TPOFF = 14, + R_386_TLS_IE = 15, + R_386_TLS_GOTIE = 16, + R_386_TLS_LE = 17, + R_386_TLS_GD = 18, + R_386_TLS_LDM = 19, + R_386_16 = 20, + R_386_PC16 = 21, + R_386_8 = 22, + R_386_PC8 = 23, + R_386_TLS_GD_32 = 24, + R_386_TLS_GD_PUSH = 25, + R_386_TLS_GD_CALL = 26, + R_386_TLS_GD_POP = 27, + R_386_TLS_LDM_32 = 28, + R_386_TLS_LDM_PUSH = 29, + R_386_TLS_LDM_CALL = 30, + R_386_TLS_LDM_POP = 31, + R_386_TLS_LDO_32 = 32, + R_386_TLS_IE_32 = 33, + R_386_TLS_LE_32 = 34, + R_386_TLS_DTPMOD32 = 35, + R_386_TLS_DTPOFF32 = 36, + R_386_TLS_TPOFF32 = 37, + R_386_SIZE32 = 38, + R_386_TLS_GOTDESC = 39, + R_386_TLS_DESC_CALL = 40, + R_386_TLS_DESC = 41, + R_386_IRELATIVE = 42, + R_386_GOT32X = 43, + R_386_NUM = 44, - R_X86_64_NONE = 0, - R_X86_64_64 = 1, - R_X86_64_PC32 = 2, - R_X86_64_GOT32 = 3, - R_X86_64_PLT32 = 4, - R_X86_64_COPY = 5, - R_X86_64_GLOB_DAT = 6, - R_X86_64_JUMP_SLOT = 7, - R_X86_64_RELATIVE = 8, - R_X86_64_GOTPCREL = 9, - R_X86_64_32 = 10, - R_X86_64_32S = 11, - R_X86_64_16 = 12, + R_X86_64_NONE = 0, + R_X86_64_64 = 1, + R_X86_64_PC32 = 2, + R_X86_64_GOT32 = 3, + R_X86_64_PLT32 = 4, + R_X86_64_COPY = 5, + R_X86_64_GLOB_DAT = 6, + R_X86_64_JUMP_SLOT = 7, + R_X86_64_RELATIVE = 8, + R_X86_64_GOTPCREL = 9, + R_X86_64_32 = 10, + R_X86_64_32S = 11, + R_X86_64_16 = 12, + R_X86_64_PC16 = 13, + R_X86_64_8 = 14, + R_X86_64_PC8 = 15, + R_X86_64_DTPMOD64 = 16, + R_X86_64_DTPOFF64 = 17, + R_X86_64_TPOFF64 = 18, + R_X86_64_TLSGD = 19, + R_X86_64_TLSLD = 20, + R_X86_64_DTPOFF32 = 21, + R_X86_64_GOTTPOFF = 22, + R_X86_64_TPOFF32 = 23, + R_X86_64_PC64 = 24, + R_X86_64_GOTOFF64 = 25, + R_X86_64_GOTPC32 = 26, + R_X86_64_GOT64 = 27, + R_X86_64_GOTPCREL64 = 28, + R_X86_64_GOTPC64 = 29, + R_X86_64_GOTPLT64 = 30, + R_X86_64_PLTOFF64 = 31, + R_X86_64_SIZE32 = 32, + R_X86_64_SIZE64 = 33, + R_X86_64_GOTPC32_TLSDESC = 34, + R_X86_64_TLSDESC_CALL = 35, + R_X86_64_TLSDESC = 36, + R_X86_64_IRELATIVE = 37, + R_X86_64_RELATIVE64 = 38, + R_X86_64_GOTPCRELX = 41, + R_X86_64_REX_GOTPCRELX = 42, + R_X86_64_NUM = 43 }; -enum ProgFlags_Types +enum SegmentFlags { - PF_X = 1, - PF_W = 2, - PF_R = 4 + PF_X = 1, + PF_W = 2, + PF_R = 4, + PF_MASKPROC = 0xf0000000 }; -enum StT_Bindings +enum SymbolBindings { - /** - * @brief Local symbol. Symbol is not visible outside the object file. - */ - STB_LOCAL = 0, - /** - * @brief Global symbol. These symbols are visible to all object files being combined. - */ - STB_GLOBAL = 1, - /** - * @brief Weak symbols. These symbols are like global symbols, but their definitions are not required. Weak symbols are not visible outside the object file containing their definition. - */ - STB_WEAK = 2, - /** - * @brief Values in this inclusive range are reserved for operating system-specific semantics. - */ - STB_LOOS = 10, - /** - * @brief Values in this inclusive range are reserved for operating system-specific semantics. - */ - STB_HIOS = 12, - /** - * @brief Values in this inclusive range are reserved for processor-specific semantics. - */ - STB_LOPROC = 13, - /** - * @brief Values in this inclusive range are reserved for processor-specific semantics. - */ - STB_HIPROC = 15 + STB_LOCAL = 0, + STB_GLOBAL = 1, + STB_WEAK = 2, + STB_LOOS = 10, + STB_HIOS = 12, + STB_LOPROC = 13, + STB_HIPROC = 15 }; -enum StT_Types +enum SymbolTypes { - STT_NOTYPE = 0, // No type - STT_OBJECT = 1, // Variables, arrays, etc. - STT_FUNC = 2 // Methods or functions + STT_NOTYPE = 0, + STT_OBJECT = 1, + STT_FUNC = 2, + STT_SECTION = 3, + STT_FILE = 4, + STT_COMMON = 5, + STT_LOOS = 10, + STT_HIOS = 12, + STT_LOPROC = 13, + STT_SPARC_REGISTER = 13, + STT_HIPROC = 15 }; enum SegmentTypes { - PT_NULL = 0, - PT_LOAD = 1, - PT_DYNAMIC = 2, - PT_INTERP = 3, - PT_NOTE = 4, - PT_SHLIB = 5, - PT_PHDR = 6, - PT_TLS = 7, - PT_LOSUNW = 0x6ffffffa, - PT_SUNWBSS = 0x6ffffffb, - PT_SUNWSTACK = 0x6ffffffa, - PT_HISUNW = 0x6fffffff, - PT_LOPROC = 0x70000000, - PT_HIPROC = 0x7fffffff + PT_NULL = 0, + PT_LOAD = 1, + PT_DYNAMIC = 2, + PT_INTERP = 3, + PT_NOTE = 4, + PT_SHLIB = 5, + PT_PHDR = 6, + PT_TLS = 7, + PT_LOSUNW = 0x6ffffffa, + PT_SUNWBSS = 0x6ffffffb, + PT_SUNWSTACK = 0x6ffffffa, + PT_HISUNW = 0x6fffffff, + PT_LOPROC = 0x70000000, + PT_HIPROC = 0x7fffffff }; -/* https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-42444/index.html */ enum DynamicArrayTags { - DT_NULL = 0, - DT_NEEDED = 1, - DT_PLTRELSZ = 2, - DT_PLTGOT = 3, - DT_HASH = 4, - DT_STRTAB = 5, - DT_SYMTAB = 6, - DT_RELA = 7, - DT_RELASZ = 8, - DT_RELAENT = 9, - DT_STRSZ = 10, - DT_SYMENT = 11, - DT_INIT = 12, - DT_FINI = 13, - DT_SONAME = 14, - DT_RPATH = 15, - DT_SYMBOLIC = 16, - DT_REL = 17, - DT_RELSZ = 18, - DT_RELENT = 19, - DT_PLTREL = 20, - DT_DEBUG = 21, - DT_TEXTREL = 22, - DT_JMPREL = 23, - DT_BIND_NOW = 24, - DT_INIT_ARRAY = 25, - DT_FINI_ARRAY = 26, - DT_INIT_ARRAYSZ = 27, - DT_FINI_ARRAYSZ = 28, - DT_RUNPATH = 29, - DT_FLAGS = 30, - DT_ENCODING = 32, - DT_PREINIT_ARRAY = 32, - DT_PREINIT_ARRAYSZ = 33, - DT_LOOS = 0x6000000d, - DT_SUNW_RTLDINF = 0x6000000e, - DT_HIOS = 0x6ffff000, - DT_VALRNGLO = 0x6ffffd00, - DT_CHECKSUM = 0x6ffffdf8, - DT_PLTPADSZ = 0x6ffffdf9, - DT_MOVEENT = 0x6ffffdfa, - DT_MOVESZ = 0x6ffffdfb, - DT_FEATURE_1 = 0x6ffffdfc, - DT_POSFLAG_1 = 0x6ffffdfd, - DT_SYMINSZ = 0x6ffffdfe, - DT_SYMINENT = 0x6ffffdff, - DT_VALRNGHI = 0x6ffffdff, - DT_ADDRRNGLO = 0x6ffffe00, - DT_CONFIG = 0x6ffffefa, - DT_DEPAUDIT = 0x6ffffefb, - DT_AUDIT = 0x6ffffefc, - DT_PLTPAD = 0x6ffffefd, - DT_MOVETAB = 0x6ffffefe, - DT_SYMINFO = 0x6ffffeff, - DT_ADDRRNGHI = 0x6ffffeff, - DT_RELACOUNT = 0x6ffffff9, - DT_RELCOUNT = 0x6ffffffa, - DT_FLAGS_1 = 0x6ffffffb, - DT_VERDEF = 0x6ffffffc, - DT_VERDEFNUM = 0x6ffffffd, - DT_VERNEED = 0x6ffffffe, - DT_VERNEEDNUM = 0x6fffffff, - DT_LOPROC = 0x70000000, - DT_SPARC_REGISTER = 0x70000001, - DT_AUXILIARY = 0x7ffffffd, - DT_USED = 0x7ffffffe, - DT_FILTER = 0x7fffffff, - DT_HIPROC = 0x7fffffff + DT_NULL = 0, + DT_NEEDED = 1, + DT_PLTRELSZ = 2, + DT_PLTGOT = 3, + DT_HASH = 4, + DT_STRTAB = 5, + DT_SYMTAB = 6, + DT_RELA = 7, + DT_RELASZ = 8, + DT_RELAENT = 9, + DT_STRSZ = 10, + DT_SYMENT = 11, + DT_INIT = 12, + DT_FINI = 13, + DT_SONAME = 14, + DT_RPATH = 15, + DT_SYMBOLIC = 16, + DT_REL = 17, + DT_RELSZ = 18, + DT_RELENT = 19, + DT_PLTREL = 20, + DT_DEBUG = 21, + DT_TEXTREL = 22, + DT_JMPREL = 23, + DT_BIND_NOW = 24, + DT_INIT_ARRAY = 25, + DT_FINI_ARRAY = 26, + DT_INIT_ARRAYSZ = 27, + DT_FINI_ARRAYSZ = 28, + DT_RUNPATH = 29, + DT_FLAGS = 30, + DT_ENCODING = 32, + DT_PREINIT_ARRAY = 32, + DT_PREINIT_ARRAYSZ = 33, + DT_LOOS = 0x6000000d, + DT_SUNW_RTLDINF = 0x6000000e, + DT_HIOS = 0x6ffff000, + DT_VALRNGLO = 0x6ffffd00, + DT_CHECKSUM = 0x6ffffdf8, + DT_PLTPADSZ = 0x6ffffdf9, + DT_MOVEENT = 0x6ffffdfa, + DT_MOVESZ = 0x6ffffdfb, + DT_FEATURE_1 = 0x6ffffdfc, + DT_POSFLAG_1 = 0x6ffffdfd, + DT_SYMINSZ = 0x6ffffdfe, + DT_SYMINENT = 0x6ffffdff, + DT_VALRNGHI = 0x6ffffdff, + DT_ADDRRNGLO = 0x6ffffe00, + DT_CONFIG = 0x6ffffefa, + DT_DEPAUDIT = 0x6ffffefb, + DT_AUDIT = 0x6ffffefc, + DT_PLTPAD = 0x6ffffefd, + DT_MOVETAB = 0x6ffffefe, + DT_SYMINFO = 0x6ffffeff, + DT_ADDRRNGHI = 0x6ffffeff, + DT_RELACOUNT = 0x6ffffff9, + DT_RELCOUNT = 0x6ffffffa, + DT_FLAGS_1 = 0x6ffffffb, + DT_VERDEF = 0x6ffffffc, + DT_VERDEFNUM = 0x6ffffffd, + DT_VERNEED = 0x6ffffffe, + DT_VERNEEDNUM = 0x6fffffff, + DT_LOPROC = 0x70000000, + DT_SPARC_REGISTER = 0x70000001, + DT_AUXILIARY = 0x7ffffffd, + DT_USED = 0x7ffffffe, + DT_FILTER = 0x7fffffff, + DT_HIPROC = 0x7fffffff }; -// used for Elf64_Sym st_info +/* Used for Elf64_Sym st_info */ #define ELF32_ST_BIND(info) ((info) >> 4) #define ELF32_ST_TYPE(info) ((info)&0xf) #define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf)) @@ -406,7 +313,7 @@ enum DynamicArrayTags #define ELF64_ST_TYPE(info) ((info)&0xf) #define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf)) -// used for Elf64_Sym st_other +/* Used for Elf64_Sym st_other */ #define ELF32_ST_VISIBILITY(o) ((o)&0x3) #define ELF64_ST_VISIBILITY(o) ((o)&0x3) @@ -427,68 +334,395 @@ enum DynamicArrayTags #define SHN_UNDEF 0 #define SHN_ABS 0xfff1 -#define SHT_NOBITS 8 -#define SHT_REL 9 - #define SHF_WRITE 0x1 #define SHF_ALLOC 0x2 -#define EM_386 0x3 // x86 Machine Type -#define EM_X86_64 0x3E // 64bit -#define EM_ARM 0x28 // ARM -#define EM_AARCH64 0xb7 // ARM64 +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#define EM_IAMCU 6 /* Intel MCU */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS I Architecture */ +#define EM_S370 9 /* IBM System/370 Processor */ +#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-endian */ +#define EM_PARISC 15 /* Hewlett-Packard PA-RISC */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* 64-bit PowerPC */ +#define EM_S390 22 /* IBM System/390 Processor */ +#define EM_SPU 23 /* IBM SPU/SPC */ +#define EM_V800 36 /* NEC V800 */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* ARM 32-bit architecture (AARCH32) */ +#define EM_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC Version 9 */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor */ +#define EM_ARC 45 /* Argonaut RISC Core, Argonaut Technologies Inc. */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel IA-64 processor architecture */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola ColdFire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embedded RISC processor */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Star*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ embedded processor family */ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ +#define EM_PDP10 64 /* Digital Equipment Corp. PDP-10 */ +#define EM_PDP11 65 /* Digital Equipment Corp. PDP-11 */ +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 bit microcontroller */ +#define EM_ST7 68 /* STMicroelectronics ST7 8-bit microcontroller */ +#define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit microcontroller */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_COMPACT 93 /* ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5) */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Processor */ +#define EM_NS32K 97 /* National Semiconductor 32000 series */ +#define EM_TPC 98 /* Tenor Network TPC processor */ +#define EM_SNP1K 99 /* Trebia SNP 1000 processor */ +#define EM_ST200 100 /* STMicroelectronics (www.st.com) ST200 microcontroller */ +#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family */ +#define EM_MAX 102 /* MAX Processor */ +#define EM_CR 103 /* National Semiconductor CompactRISC microprocessor */ +#define EM_F2MC16 104 /* Fujitsu F2MC16 */ +#define EM_MSP430 105 /* Texas Instruments embedded microcontroller msp430 */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor */ +#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors */ +#define EM_SEP 108 /* Sharp embedded microprocessor */ +#define EM_ARCA 109 /* Arca RISC Microprocessor */ +#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University */ +#define EM_EXCESS 111 /* eXcess: 16/32/64-bit configurable embedded CPU */ +#define EM_DXP 112 /* Icera Semiconductor Inc. Deep Execution Processor */ +#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ +#define EM_CRX 114 /* National Semiconductor CompactRISC CRX microprocessor */ +#define EM_XGATE 115 /* Motorola XGATE embedded processor */ +#define EM_C166 116 /* Infineon C16x/XC16x processor */ +#define EM_M16C 117 /* Renesas M16C series microprocessors */ +#define EM_DSPIC30F 118 /* Microchip Technology dsPIC30F Digital Signal Controller */ +#define EM_CE 119 /* Freescale Communication Engine RISC core */ +#define EM_M32C 120 /* Renesas M32C series microprocessors */ +#define EM_TSK3000 131 /* Altium TSK3000 core */ +#define EM_RS08 132 /* Freescale RS08 embedded processor */ +#define EM_SHARC 133 /* Analog Devices SHARC family of 32-bit DSP processors */ +#define EM_ECOG2 134 /* Cyan Technology eCOG2 microprocessor */ +#define EM_SCORE7 135 /* Sunplus S+core7 RISC processor */ +#define EM_DSP24 136 /* New Japan Radio (NJR) 24-bit DSP Processor */ +#define EM_VIDEOCORE3 137 /* Broadcom VideoCore III processor */ +#define EM_LATTICEMICO32 138 /* RISC processor for Lattice FPGA architecture */ +#define EM_SE_C17 139 /* Seiko Epson C17 family */ +#define EM_TI_C6000 140 /* The Texas Instruments TMS320C6000 DSP family */ +#define EM_TI_C2000 141 /* The Texas Instruments TMS320C2000 DSP family */ +#define EM_TI_C5500 142 /* The Texas Instruments TMS320C55x DSP family */ +#define EM_TI_ARP32 143 /* Texas Instruments Application Specific RISC Processor, 32bit fetch */ +#define EM_TI_PRU 144 /* Texas Instruments Programmable Realtime Unit */ +#define EM_MMDSP_PLUS 160 /* STMicroelectronics 64bit VLIW Data Signal Processor */ +#define EM_CYPRESS_M8C 161 /* Cypress M8C microprocessor */ +#define EM_R32C 162 /* Renesas R32C series microprocessors */ +#define EM_TRIMEDIA 163 /* NXP Semiconductors TriMedia architecture family */ +#define EM_QDSP6 164 /* QUALCOMM DSP6 Processor */ +#define EM_8051 165 /* Intel 8051 and variants */ +#define EM_STXP7X 166 /* STMicroelectronics STxP7x family of configurable and extensible RISC processors */ +#define EM_NDS32 167 /* Andes Technology compact code size embedded RISC processor family */ +#define EM_ECOG1 168 /* Cyan Technology eCOG1X family */ +#define EM_ECOG1X 168 /* Cyan Technology eCOG1X family */ +#define EM_MAXQ30 169 /* Dallas Semiconductor MAXQ30 Core Micro-controllers */ +#define EM_XIMO16 170 /* New Japan Radio (NJR) 16-bit DSP Processor */ +#define EM_MANIK 171 /* M2000 Reconfigurable RISC Microprocessor */ +#define EM_CRAYNV2 172 /* Cray Inc. NV2 vector architecture */ +#define EM_RX 173 /* Renesas RX family */ +#define EM_METAG 174 /* Imagination Technologies META processor architecture */ +#define EM_MCST_ELBRUS 175 /* MCST Elbrus general purpose hardware architecture */ +#define EM_ECOG16 176 /* Cyan Technology eCOG16 family */ +#define EM_CR16 177 /* National Semiconductor CompactRISC CR16 16-bit microprocessor */ +#define EM_ETPU 178 /* Freescale Extended Time Processing Unit */ +#define EM_SLE9X 179 /* Infineon Technologies SLE9X core */ +#define EM_L10M 180 /* Intel L10M */ +#define EM_K10M 181 /* Intel K10M */ +#define EM_AARCH64 183 /* ARM 64-bit architecture (AARCH64) */ +#define EM_AVR32 185 /* Atmel Corporation 32-bit microprocessor family */ +#define EM_STM8 186 /* STMicroeletronics STM8 8-bit microcontroller */ +#define EM_TILE64 187 /* Tilera TILE64 multicore architecture family */ +#define EM_TILEPRO 188 /* Tilera TILEPro multicore architecture family */ +#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze 32-bit RISC soft processor core */ +#define EM_CUDA 190 /* NVIDIA CUDA architecture */ +#define EM_TILEGX 191 /* Tilera TILE-Gx multicore architecture family */ +#define EM_CLOUDSHIELD 192 /* CloudShield architecture family */ +#define EM_COREA_1ST 193 /* KIPO-KAIST Core-A 1st generation processor family */ +#define EM_COREA_2ND 194 /* KIPO-KAIST Core-A 2nd generation processor family */ +#define EM_ARC_COMPACT2 195 /* Synopsys ARCompact V2 */ +#define EM_OPEN8 196 /* Open8 8-bit RISC soft processor core */ +#define EM_RL78 197 /* Renesas RL78 family */ +#define EM_VIDEOCORE5 198 /* Broadcom VideoCore V processor */ +#define EM_78KOR 199 /* Renesas 78KOR family */ +#define EM_56800EX 200 /* Freescale 56800EX Digital Signal Controller (DSC) */ +#define EM_BA1 201 /* Beyond BA1 CPU architecture */ +#define EM_BA2 202 /* Beyond BA2 CPU architecture */ +#define EM_XCORE 203 /* XMOS xCORE processor family */ +#define EM_MCHP_PIC 204 /* Microchip 8-bit PIC(r) family */ +#define EM_INTEL205 205 /* Reserved by Intel */ +#define EM_INTEL206 206 /* Reserved by Intel */ +#define EM_INTEL207 207 /* Reserved by Intel */ +#define EM_INTEL208 208 /* Reserved by Intel */ +#define EM_INTEL209 209 /* Reserved by Intel */ +#define EM_KM32 210 /* KM211 KM32 32-bit processor */ +#define EM_KMX32 211 /* KM211 KMX32 32-bit processor */ +#define EM_KMX16 212 /* KM211 KMX16 16-bit processor */ +#define EM_KMX8 213 /* KM211 KMX8 8-bit processor */ +#define EM_KVARC 214 /* KM211 KVARC processor */ +#define EM_CDP 215 /* Paneve CDP architecture family */ +#define EM_COGE 216 /* Cognitive Smart Memory Processor */ +#define EM_COOL 217 /* Bluechip Systems CoolEngine */ +#define EM_NORC 218 /* Nanoradio Optimized RISC */ +#define EM_CSR_KALIMBA 219 /* CSR Kalimba architecture family */ +#define EM_Z80 220 /* Zilog Z80 */ +#define EM_VISIUM 221 /* Controls and Data Services VISIUMcore processor */ +#define EM_FT32 222 /* FTDI Chip FT32 high performance 32-bit RISC architecture */ +#define EM_MOXIE 223 /* Moxie processor family */ +#define EM_AMDGPU 224 /* AMD GPU architecture */ +#define EM_RISCV 243 /* RISC-V */ -#define EV_CURRENT 0x1 // ELF Current Version +#define EV_NONE 0x0 /* Invalid ELF Version */ +#define EV_CURRENT 0x1 /* ELF Current Version */ -#define ELFMAG0 0x7F // e_ident[EI_MAG0] -#define ELFMAG1 'E' // e_ident[EI_MAG1] -#define ELFMAG2 'L' // e_ident[EI_MAG2] -#define ELFMAG3 'F' // e_ident[EI_MAG3] +#define ELFMAG0 0x7F +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' -#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATANONE 0 #define ELFDATA2LSB 1 #define ELFDATA2MSB 2 -#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASSNONE 0 #define ELFCLASS32 1 #define ELFCLASS64 2 #define ELFCLASSNUM 3 -#define SHT_NULL 0 /* Section header table entry unused */ -#define SHT_PROGBITS 1 /* Program data */ -#define SHT_SYMTAB 2 /* Symbol table */ -#define SHT_STRTAB 3 /* String table */ -#define SHT_RELA 4 /* Relocation entries with addends */ -#define SHT_HASH 5 /* Symbol hash table */ -#define SHT_DYNAMIC 6 /* Dynamic linking information */ -#define SHT_NOTE 7 /* Notes */ -#define SHT_NOBITS 8 /* Program space with no data (bss) */ -#define SHT_REL 9 /* Relocation entries, no addends */ -#define SHT_SHLIB 10 /* Reserved */ -#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ -#define SHT_INIT_ARRAY 14 /* Array of constructors */ -#define SHT_FINI_ARRAY 15 /* Array of destructors */ -#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ -#define SHT_GROUP 17 /* Section group */ -#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ -#define SHT_NUM 19 /* Number of defined types. */ -#define SHT_LOOS 0x60000000 /* Start OS-specific. */ -#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ -#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ -#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ -#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ -#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ -#define SHT_SUNW_move 0x6ffffffa -#define SHT_SUNW_COMDAT 0x6ffffffb -#define SHT_SUNW_syminfo 0x6ffffffc -#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ -#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ -#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ -#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ -#define SHT_HIOS 0x6fffffff /* End OS-specific type */ -#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ -#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ -#define SHT_LOUSER 0x80000000 /* Start of application-specific */ -#define SHT_HIUSER 0x8fffffff /* End of application-specific */ +enum SpecialSections +{ + SHT_NULL = 0, + SHT_PROGBITS = 1, + SHT_SYMTAB = 2, + SHT_STRTAB = 3, + SHT_RELA = 4, + SHT_HASH = 5, + SHT_DYNAMIC = 6, + SHT_NOTE = 7, + SHT_NOBITS = 8, + SHT_REL = 9, + SHT_SHLIB = 10, + SHT_DYNSYM = 11, + SHT_INIT_ARRAY = 14, + SHT_FINI_ARRAY = 15, + SHT_PREINIT_ARRAY = 16, + SHT_GROUP = 17, + SHT_SYMTAB_SHNDX = 18, + SHT_NUM = 19, + SHT_LOOS = 0x60000000, + SHT_GNU_ATTRIBUTES = 0x6ffffff5, + SHT_GNU_HASH = 0x6ffffff6, + SHT_GNU_LIBLIST = 0x6ffffff7, + SHT_CHECKSUM = 0x6ffffff8, + SHT_LOSUNW = 0x6ffffffa, + SHT_SUNW_move = 0x6ffffffa, + SHT_SUNW_COMDAT = 0x6ffffffb, + SHT_SUNW_syminfo = 0x6ffffffc, + SHT_GNU_verdef = 0x6ffffffd, + SHT_GNU_verneed = 0x6ffffffe, + SHT_GNU_versym = 0x6fffffff, + SHT_HISUNW = 0x6fffffff, + SHT_HIOS = 0x6fffffff, + SHT_LOPROC = 0x70000000, + SHT_HIPROC = 0x7fffffff, + SHT_LOUSER = 0x80000000, + SHT_HIUSER = 0x8fffffff +}; + +typedef struct elf32_hdr +{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct elf64_hdr +{ + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +typedef struct elf32_shdr +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct elf64_shdr +{ + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +typedef struct +{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct +{ + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +typedef struct elf32_rel +{ + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel +{ + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + +typedef struct elf32_sym +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym +{ + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +struct Elf32_Dyn +{ + Elf32_Sword d_tag; + union + { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +}; + +struct Elf64_Dyn +{ + Elf64_Sxword d_tag; + union + { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +}; + +typedef struct +{ + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; #endif // !__FENNIX_KERNEL_ELF_H__ diff --git a/include/emmintrin.h b/include/emmintrin.h new file mode 100644 index 0000000..878aadf --- /dev/null +++ b/include/emmintrin.h @@ -0,0 +1,23 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_EMMINTRIN_H__ +#define __FENNIX_KERNEL_EMMINTRIN_H__ + +/* stub header */ + +#endif // !__FENNIX_KERNEL_EMMINTRIN_H__ diff --git a/include/exec.hpp b/include/exec.hpp index 9682991..caeb0bc 100644 --- a/include/exec.hpp +++ b/include/exec.hpp @@ -23,126 +23,168 @@ #include #include #include +#include #include namespace Execute { - enum BinaryType - { - BinTypeInvalid, - BinTypeFex, - BinTypeELF, - BinTypePE, - BinTypeNE, - BinTypeMZ, - BinTypeUnknown - }; + enum BinaryType + { + BinTypeInvalid, + BinTypeFex, + BinTypeELF, + BinTypePE, + BinTypeNE, + BinTypeMZ, + BinTypeUnknown + }; - enum ExStatus - { - Unknown, - OK, - Unsupported, - GenericError, - InvalidFile, - InvalidFileFormat, - InvalidFileHeader, - InvalidFileData, - InvalidFileEntryPoint, - InvalidFilePath - }; + enum ExStatus + { + Unknown, + OK, + Unsupported, + GenericError, + LoadingProcedureFailed, + InvalidFile, + InvalidFileFormat, + InvalidFileHeader, + InvalidFileData, + InvalidFileEntryPoint, + InvalidFilePath + }; - struct SpawnData - { - ExStatus Status; - Tasking::PCB *Process; - Tasking::TCB *Thread; - }; + struct SpawnData + { + ExStatus Status; + Tasking::PCB *Process; + Tasking::TCB *Thread; + }; - struct SharedLibraries - { - char Identifier[64]; - uint64_t Timeout; - int RefCount; + struct SharedLibrary + { + char Identifier[64]; + char Path[256]; + uint64_t Timeout; + int RefCount; - uintptr_t Address; - uintptr_t MemoryImage; - size_t Length; - }; + uintptr_t MemoryImage; + size_t Length; + }; - struct ELFBaseLoad - { - bool Success; - bool Interpreter; - SpawnData sd; - Tasking::IP InstructionPointer; + struct ELFBaseLoad + { + bool Success; + bool Interpreter; + SpawnData sd; + Tasking::IP InstructionPointer; - std::vector NeededLibraries; - void *MemoryImage; - void *VirtualMemoryImage; + std::vector NeededLibraries; + void *MemoryImage; + void *VirtualMemoryImage; - /* This should be deleted after copying the allocated pages to the thread - Intended to be used only inside BaseLoad.cpp */ - Memory::MemMgr *TmpMem; + /* This should be deleted after copying the allocated pages to the thread + Intended to be used only inside BaseLoad.cpp */ + Memory::MemMgr *TmpMem; - /* Same as above, for BaseLoad.cpp only */ - std::vector auxv; - }; + /* Same as above, for BaseLoad.cpp only */ + std::vector auxv; + }; - struct MmImage - { - void *Physical; - void *Virtual; - }; + struct MmImage + { + void *Physical; + void *Virtual; + }; - BinaryType GetBinaryType(void *Image); - BinaryType GetBinaryType(char *Path); + class ELFObject + { + private: + ELFBaseLoad BaseLoadInfo{}; - SpawnData Spawn(char *Path, const char **argv, const char **envp); + ELFBaseLoad LoadExec_x86_32(VirtualFileSystem::File &ElfFile, + Tasking::PCB *TargetProcess); - ELFBaseLoad ELFLoad(char *Path, const char **argv, const char **envp, - Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native); + ELFBaseLoad LoadExec_x86_64(VirtualFileSystem::File &ElfFile, + Tasking::PCB *TargetProcess); - Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header); - Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index); - char *GetELFStringTable(Elf64_Ehdr *Header); - char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset); - Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name); - uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index); - Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag); + ELFBaseLoad LoadDyn_x86_32(VirtualFileSystem::File &ElfFile, + Tasking::PCB *TargetProcess, + bool IsLibrary); - /** - * @brief Create a ELF Memory Image - * - * @param mem The memory manager to use - * @param pV Memory::Virtual object to use - * @param ElfFile ELF file loaded in memory (FULL FILE) - * @param Length Length of @p ElfFile - * @return The Memory Image (Physical and Virtual) - */ - MmImage ELFCreateMemoryImage(Memory::MemMgr *mem, Memory::Virtual &pV, void *ElfFile, size_t Length); + ELFBaseLoad LoadDyn_x86_64(VirtualFileSystem::File &ElfFile, + Tasking::PCB *TargetProcess, + bool IsLibrary); - uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, Memory::Virtual &pV, const char *Interpreter); + public: + ELFBaseLoad GetBaseLoadInfo() { return BaseLoadInfo; } + bool IsValid() { return BaseLoadInfo.Success; } - ELFBaseLoad ELFLoadRel(void *ElfFile, - VirtualFileSystem::File &ExFile, - Tasking::PCB *Process); + ELFObject(char *AbsolutePath, + Tasking::PCB *TargetProcess, + bool IsLibrary = false); + ~ELFObject(); + }; - ELFBaseLoad ELFLoadExec(void *ElfFile, - VirtualFileSystem::File &ExFile, - Tasking::PCB *Process); + /* Full binary size. */ + BinaryType GetBinaryType(void *Image); - ELFBaseLoad ELFLoadDyn(void *ElfFile, - VirtualFileSystem::File &ExFile, - Tasking::PCB *Process); + BinaryType GetBinaryType(char *Path); - void StartExecuteService(); - bool AddLibrary(char *Identifier, - void *ElfImage, - size_t Length, - const Memory::Virtual &pV = Memory::Virtual()); - void SearchLibrary(char *Identifier); - SharedLibraries GetLibrary(char *Identifier); + SpawnData Spawn(char *Path, const char **argv, const char **envp); + + ELFBaseLoad ELFLoad(char *Path, const char **argv, const char **envp, + Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native); + + void ELFInterpreterIPCThread(Tasking::PCB *TargetProcess, + std::string *TargetPath, + void *MemoryImage, + std::vector *NeededLibraries); + + bool ELFIs64(void *Header); + Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header); + Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index); + char *GetELFStringTable(Elf64_Ehdr *Header); + char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset); + Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name); + Elf64_Sym ELFLookupSymbol(VirtualFileSystem::File &ElfFile, const char *Name); + uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index); + + std::vector ELFGetSymbolType_x86_64(VirtualFileSystem::File &ElfFile, SegmentTypes Tag); + std::vector ELFGetSymbolType_x86_32(VirtualFileSystem::File &ElfFile, SegmentTypes Tag); + + std::vector ELFGetSections_x86_64(VirtualFileSystem::File &ElfFile, const char *SectionName); + std::vector ELFGetSections_x86_32(VirtualFileSystem::File &ElfFile, const char *SectionName); + + std::vector ELFGetDynamicTag_x86_64(VirtualFileSystem::File &ElfFile, DynamicArrayTags Tag); + std::vector ELFGetDynamicTag_x86_32(VirtualFileSystem::File &ElfFile, DynamicArrayTags Tag); + + void CopyLOADSegments(VirtualFileSystem::File &ElfFile, uintptr_t HdrsBase, uintptr_t PhysicalBase); + void GetBaseAndSize(VirtualFileSystem::File &ElfFile, uintptr_t &Base, size_t &Size); + + /** + * @brief Create a ELF Memory Image + * + * @param mem The memory manager to use + * @param vmm Memory::Virtual object to use + * @param ElfFile The ELF File + * @param Length Length of @p ElfFile + * @return The Memory Image (Physical and Virtual) + */ + MmImage ELFCreateMemoryImage(Memory::MemMgr *mem, + Memory::Virtual &vmm, + VirtualFileSystem::File &ElfFile, + size_t Length); + + uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, + Memory::Virtual &vmm, + const char *Interpreter); + + void LibraryManagerService(); + bool AddLibrary(char *Identifier, + VirtualFileSystem::File &ExFile, + const Memory::Virtual &vmm = Memory::Virtual()); + SharedLibrary GetLibrary(char *Identifier); } #endif // !__FENNIX_KERNEL_FILE_EXECUTE_H__ diff --git a/include/filesystem.hpp b/include/filesystem.hpp index 5b2e3b8..9c8c6dc 100644 --- a/include/filesystem.hpp +++ b/include/filesystem.hpp @@ -34,8 +34,8 @@ namespace VirtualFileSystem typedef size_t (*OperationMount)(const char *, unsigned long, const void *); typedef size_t (*OperationUmount)(int); - typedef size_t (*OperationRead)(Node *node, size_t Offset, size_t Size, uint8_t *Buffer); - typedef size_t (*OperationWrite)(Node *node, size_t Offset, size_t Size, uint8_t *Buffer); + typedef size_t (*OperationRead)(Node *node, size_t Size, uint8_t *Buffer); + typedef size_t (*OperationWrite)(Node *node, size_t Size, uint8_t *Buffer); typedef void (*OperationOpen)(Node *node, uint8_t Mode, uint8_t Flags); typedef void (*OperationClose)(Node *node); typedef size_t (*OperationSync)(void); @@ -46,14 +46,14 @@ namespace VirtualFileSystem #define MountFSFunction(name) size_t name(const char *unknown0, unsigned long unknown1, const uint8_t *unknown2) #define UMountFSFunction(name) size_t name(int unknown0) -#define ReadFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Offset, size_t Size, uint8_t *Buffer) -#define WriteFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Offset, size_t Size, uint8_t *Buffer) +#define ReadFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Size, uint8_t *Buffer) +#define WriteFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Size, uint8_t *Buffer) #define OpenFSFunction(name) void name(VirtualFileSystem::Node *node, uint8_t Mode, uint8_t Flags) #define CloseFSFunction(name) void name(VirtualFileSystem::Node *node) #define SyncFSFunction(name) size_t name(void) #define CreateFSFunction(name) void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength) #define MkdirFSFunction(name) void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength) -#define SeekFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Offset, uint8_t Whence) +#define SeekFSFunction(name) off_t name(VirtualFileSystem::Node *node, off_t Offset, uint8_t Whence) enum FileStatus { @@ -120,7 +120,7 @@ namespace VirtualFileSystem uint64_t UserIdentifier = 0, GroupIdentifier = 0; uintptr_t Address = 0; size_t Length = 0; - size_t Offset = 0; + off_t Offset = 0; Node *Parent = nullptr; FileSystemOperations *Operator = nullptr; /* For root node: @@ -135,9 +135,37 @@ namespace VirtualFileSystem { char Name[FILENAME_LENGTH]; FileStatus Status; - Node *node; + bool IsOK() + { + return Status == FileStatus::OK; + } - bool IsOK() { return Status == FileStatus::OK; } + size_t GetLength() + { + return node->Length; + } + + std::vector GetChildren() + { + return node->Children; + } + + NodeFlags GetFlags() + { + return node->Flags; + } + + /** @brief Special cases only. */ + Node *GetNode() + { + return node; + } + + private: + Node *node; + off_t ContextOffset; + + friend class Virtual; }; /* Manage / etc.. */ @@ -178,8 +206,9 @@ namespace VirtualFileSystem File Mount(const char *Path, FileSystemOperations *Operator); FileStatus Unmount(File &File); - size_t Read(File &File, size_t Offset, uint8_t *Buffer, size_t Size); - size_t Write(File &File, size_t Offset, uint8_t *Buffer, size_t Size); + size_t Read(File &File, uint8_t *Buffer, size_t Size); + size_t Write(File &File, uint8_t *Buffer, size_t Size); + off_t Seek(File &File, off_t Offset, uint8_t Whence); File Open(const char *Path, Node *Parent = nullptr); FileStatus Close(File &File); diff --git a/include/memory.hpp b/include/memory.hpp index db03178..e4de1b0 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -192,9 +192,17 @@ namespace Memory uintptr_t Dirty : 1; // 6 uintptr_t PageAttributeTable : 1; // 7 uintptr_t Global : 1; // 8 - uintptr_t Available0 : 3; // 9-11 + uintptr_t Available0 : 1; // 9 + uintptr_t Available1 : 1; // 10 + uintptr_t Available2 : 1; // 11 uintptr_t Address : 40; // 12-51 - uintptr_t Available1 : 7; // 52-58 + uintptr_t Available3 : 1; // 52 + uintptr_t Available4 : 1; // 53 + uintptr_t Available5 : 1; // 54 + uintptr_t Available6 : 1; // 55 + uintptr_t Available7 : 1; // 56 + uintptr_t Available8 : 1; // 57 + uintptr_t Available9 : 1; // 58 uintptr_t ProtectionKey : 4; // 59-62 uintptr_t ExecuteDisable : 1; // 63 #elif defined(a32) @@ -207,7 +215,9 @@ namespace Memory uintptr_t Dirty : 1; // 6 uintptr_t PageAttributeTable : 1; // 7 uintptr_t Global : 1; // 8 - uintptr_t Available0 : 3; // 9-11 + uintptr_t Available0 : 1; // 9 + uintptr_t Available1 : 1; // 10 + uintptr_t Available2 : 1; // 11 uintptr_t Address : 20; // 12-31 #elif defined(aa64) #endif @@ -285,11 +295,19 @@ namespace Memory uintptr_t Dirty : 1; // 6 uintptr_t PageSize : 1; // 7 uintptr_t Global : 1; // 8 - uintptr_t Available0 : 3; // 9-11 + uintptr_t Available0 : 1; // 9 + uintptr_t Available1 : 1; // 10 + uintptr_t Available2 : 1; // 11 uintptr_t PageAttributeTable : 1; // 12 uintptr_t Reserved0 : 8; // 13-20 uintptr_t Address : 31; // 21-51 - uintptr_t Available1 : 7; // 52-58 + uintptr_t Available3 : 1; // 52 + uintptr_t Available4 : 1; // 53 + uintptr_t Available5 : 1; // 54 + uintptr_t Available6 : 1; // 55 + uintptr_t Available7 : 1; // 56 + uintptr_t Available8 : 1; // 57 + uintptr_t Available9 : 1; // 58 uintptr_t ProtectionKey : 4; // 59-62 uintptr_t ExecuteDisable : 1; // 63 } TwoMB; @@ -319,7 +337,9 @@ namespace Memory uintptr_t Dirty : 1; // 6 uintptr_t PageSize : 1; // 7 uintptr_t Global : 1; // 8 - uintptr_t Available0 : 3; // 9-11 + uintptr_t Available0 : 1; // 9 + uintptr_t Available1 : 1; // 10 + uintptr_t Available2 : 1; // 11 uintptr_t PageAttributeTable : 1; // 12 uintptr_t Address0 : 8; // 13-20 uintptr_t Reserved0 : 1; // 21 @@ -395,11 +415,19 @@ namespace Memory uintptr_t Dirty : 1; // 6 uintptr_t PageSize : 1; // 7 uintptr_t Global : 1; // 8 - uintptr_t Available0 : 3; // 9-11 + uintptr_t Available0 : 1; // 9 + uintptr_t Available1 : 1; // 10 + uintptr_t Available2 : 1; // 11 uintptr_t PageAttributeTable : 1; // 12 uintptr_t Reserved0 : 17; // 13-29 uintptr_t Address : 22; // 30-51 - uintptr_t Available1 : 7; // 52-58 + uintptr_t Available3 : 1; // 52 + uintptr_t Available4 : 1; // 53 + uintptr_t Available5 : 1; // 54 + uintptr_t Available6 : 1; // 55 + uintptr_t Available7 : 1; // 56 + uintptr_t Available8 : 1; // 57 + uintptr_t Available9 : 1; // 58 uintptr_t ProtectionKey : 4; // 59-62 uintptr_t ExecuteDisable : 1; // 63 } OneGB; @@ -754,6 +782,21 @@ namespace Memory */ void *GetPhysical(void *VirtualAddress); + /** + * @brief Get map type of the page. + * @param VirtualAddress Virtual address of the page. + * @return Map type of the page. + */ + MapType GetMapType(void *VirtualAddress); + +#ifdef a64 + PageMapLevel5 *GetPML5(void *VirtualAddress, MapType Type = MapType::FourKB); + PageMapLevel4 *GetPML4(void *VirtualAddress, MapType Type = MapType::FourKB); + PageDirectoryPointerTableEntry *GetPDPTE(void *VirtualAddress, MapType Type = MapType::FourKB); +#endif /* a64 */ + PageDirectoryEntry *GetPDE(void *VirtualAddress, MapType Type = MapType::FourKB); + PageTableEntry *GetPTE(void *VirtualAddress, MapType Type = MapType::FourKB); + /** * @brief Map page. * diff --git a/include/msexec.h b/include/msexec.h index d075cbd..4b3fe94 100644 --- a/include/msexec.h +++ b/include/msexec.h @@ -20,7 +20,7 @@ #include -// some of the code is from: https://github.com/dotnet/llilc/blob/main/include/clr/ntimage.h +/* Some of the code is from: https://github.com/dotnet/llilc/blob/main/include/clr/ntimage.h */ #define near /* __near */ #define far /* __far */ @@ -110,61 +110,61 @@ typedef double DOUBLE; #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 -typedef struct _IMAGE_DOS_HEADER // DOS .EXE header +typedef struct _IMAGE_DOS_HEADER /* DOS .EXE header */ { - USHORT e_magic; // Magic number - USHORT e_cblp; // Bytes on last page of file - USHORT e_cp; // Pages in file - USHORT e_crlc; // Relocations - USHORT e_cparhdr; // Size of header in paragraphs - USHORT e_minalloc; // Minimum extra paragraphs needed - USHORT e_maxalloc; // Maximum extra paragraphs needed - USHORT e_ss; // Initial (relative) SS value - USHORT e_sp; // Initial SP value - USHORT e_csum; // Checksum - USHORT e_ip; // Initial IP value - USHORT e_cs; // Initial (relative) CS value - USHORT e_lfarlc; // File address of relocation table - USHORT e_ovno; // Overlay number - USHORT e_res[4]; // Reserved words - USHORT e_oemid; // OEM identifier (for e_oeminfo) - USHORT e_oeminfo; // OEM information; e_oemid specific - USHORT e_res2[10]; // Reserved words - USHORT e_lfanew; // File address of new exe header + USHORT e_magic; /* Magic number */ + USHORT e_cblp; /* Bytes on last page of file */ + USHORT e_cp; /* Pages in file */ + USHORT e_crlc; /* Relocations */ + USHORT e_cparhdr; /* Size of header in paragraphs */ + USHORT e_minalloc; /* Minimum extra paragraphs needed */ + USHORT e_maxalloc; /* Maximum extra paragraphs needed */ + USHORT e_ss; /* Initial (relative) SS value */ + USHORT e_sp; /* Initial SP value */ + USHORT e_csum; /* Checksum */ + USHORT e_ip; /* Initial IP value */ + USHORT e_cs; /* Initial (relative) CS value */ + USHORT e_lfarlc; /* File address of relocation table */ + USHORT e_ovno; /* Overlay number */ + USHORT e_res[4]; /* Reserved words */ + USHORT e_oemid; /* OEM identifier (for e_oeminfo) */ + USHORT e_oeminfo; /* OEM information; e_oemid specific */ + USHORT e_res2[10]; /* Reserved words */ + USHORT e_lfanew; /* File address of new exe header */ } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; -typedef struct _IMAGE_OS2_HEADER // OS/2 .EXE header +typedef struct _IMAGE_OS2_HEADER /* OS/2 .EXE header */ { - USHORT ne_magic; // Magic number - UCHAR ne_ver; // Version number - UCHAR ne_rev; // Revision number - USHORT ne_enttab; // Offset of Entry Table - USHORT ne_cbenttab; // Number of bytes in Entry Table - UINT ne_crc; // Checksum of whole file - USHORT ne_flags; // Flag word - USHORT ne_autodata; // Automatic data segment number - USHORT ne_heap; // Initial heap allocation - USHORT ne_stack; // Initial stack allocation - UINT ne_csip; // Initial CS:IP setting - UINT ne_sssp; // Initial SS:SP setting - USHORT ne_cseg; // Count of file segments - USHORT ne_cmod; // Entries in Module Reference Table - USHORT ne_cbnrestab; // Size of non-resident name table - USHORT ne_segtab; // Offset of Segment Table - USHORT ne_rsrctab; // Offset of Resource Table - USHORT ne_restab; // Offset of resident name table - USHORT ne_modtab; // Offset of Module Reference Table - USHORT ne_imptab; // Offset of Imported Names Table - UINT ne_nrestab; // Offset of Non-resident Names Table - USHORT ne_cmovent; // Count of movable entries - USHORT ne_align; // Segment alignment shift count - USHORT ne_cres; // Count of resource segments - UCHAR ne_exetyp; // Target Operating system - UCHAR ne_flagsothers; // Other .EXE flags - USHORT ne_pretthunks; // offset to return thunks - USHORT ne_psegrefbytes; // offset to segment ref. bytes - USHORT ne_swaparea; // Minimum code swap area size - USHORT ne_expver; // Expected Windows version number + USHORT ne_magic; /* Magic number */ + UCHAR ne_ver; /* Version number */ + UCHAR ne_rev; /* Revision number */ + USHORT ne_enttab; /* Offset of Entry Table */ + USHORT ne_cbenttab; /* Number of bytes in Entry Table */ + UINT ne_crc; /* Checksum of whole file */ + USHORT ne_flags; /* Flag word */ + USHORT ne_autodata; /* Automatic data segment number */ + USHORT ne_heap; /* Initial heap allocation */ + USHORT ne_stack; /* Initial stack allocation */ + UINT ne_csip; /* Initial CS:IP setting */ + UINT ne_sssp; /* Initial SS:SP setting */ + USHORT ne_cseg; /* Count of file segments */ + USHORT ne_cmod; /* Entries in Module Reference Table */ + USHORT ne_cbnrestab; /* Size of non-resident name table */ + USHORT ne_segtab; /* Offset of Segment Table */ + USHORT ne_rsrctab; /* Offset of Resource Table */ + USHORT ne_restab; /* Offset of resident name table */ + USHORT ne_modtab; /* Offset of Module Reference Table */ + USHORT ne_imptab; /* Offset of Imported Names Table */ + UINT ne_nrestab; /* Offset of Non-resident Names Table */ + USHORT ne_cmovent; /* Count of movable entries */ + USHORT ne_align; /* Segment alignment shift count */ + USHORT ne_cres; /* Count of resource segments */ + UCHAR ne_exetyp; /* Target Operating system */ + UCHAR ne_flagsothers; /* Other .EXE flags */ + USHORT ne_pretthunks; /* offset to return thunks */ + USHORT ne_psegrefbytes; /* offset to segment ref. bytes */ + USHORT ne_swaparea; /* Minimum code swap area size */ + USHORT ne_expver; /* Expected Windows version number */ } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; typedef struct _IMAGE_SECTION_HEADER diff --git a/include/smp.hpp b/include/smp.hpp index 4a12f38..f58d422 100644 --- a/include/smp.hpp +++ b/include/smp.hpp @@ -19,6 +19,7 @@ #define __FENNIX_KERNEL_SMP_H__ #include +#include #include #include @@ -61,6 +62,9 @@ struct CPUData /** @brief Current running thread */ std::atomic CurrentThread; + /** @brief Unwind data */ + __cxa_eh_globals EHGlobals; + /** @brief Architecture-specific data. */ CPUArchData Data; diff --git a/include/task.hpp b/include/task.hpp index e20e436..5fe36c4 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -32,10 +32,13 @@ namespace Tasking { - typedef unsigned long IP; - typedef __UINTPTR_TYPE__ IPOffset; - typedef unsigned long UPID; - typedef unsigned long UTID; + /** @brief Instruction Pointer */ + typedef __UINTPTR_TYPE__ IP; + /** @brief Process ID */ + typedef int PID; + /** @brief Thread ID */ + typedef int TID; + /* @brief Token */ typedef __UINTPTR_TYPE__ Token; enum TaskArchitecture @@ -84,6 +87,16 @@ namespace Tasking Critical = 10 }; + enum KillErrorCodes : int + { + KILL_SCHEDULER_DESTRUCTION = -0xFFFF, + KILL_CXXABI_EXCEPTION = -0xECE97, + KILL_SYSCALL = -0xCA11, + KILL_OOM = -0x1008, + KILL_ERROR = -0x1, + KILL_SUCCESS = 0, + }; + struct TaskSecurity { TaskTrustLevel TrustLevel; @@ -109,11 +122,10 @@ namespace Tasking struct TCB { - UTID ID; + TID ID; char Name[256]; struct PCB *Parent; IP EntryPoint; - IPOffset Offset; int ExitCode; Memory::StackGuard *Stack; Memory::MemMgr *Memory; @@ -174,11 +186,34 @@ namespace Tasking trace("Setting kernel debug mode of thread %s to %s", Name, Enable ? "true" : "false"); Security.IsKernelDebugEnabled = Enable; } + + void SYSV_ABI_Call(uintptr_t Arg1 = 0, + uintptr_t Arg2 = 0, + uintptr_t Arg3 = 0, + uintptr_t Arg4 = 0, + uintptr_t Arg5 = 0, + uintptr_t Arg6 = 0, + void *Function = nullptr) + { + CriticalSection cs; +#if defined(a64) + this->Registers.rdi = Arg1; + this->Registers.rsi = Arg2; + this->Registers.rdx = Arg3; + this->Registers.rcx = Arg4; + this->Registers.r8 = Arg5; + this->Registers.r9 = Arg6; + if (Function != nullptr) + this->Registers.rip = (uint64_t)Function; +#else +#warning "SYSV ABI not implemented for this architecture" +#endif + } }; struct PCB { - UPID ID; + PID ID; char Name[256]; PCB *Parent; int ExitCode; @@ -243,8 +278,8 @@ namespace Tasking { private: Security SecurityManager; - UPID NextPID = 0; - UTID NextTID = 0; + PID NextPID = 0; + TID NextTID = 0; std::vector ProcessList; PCB *IdleProcess = nullptr; @@ -289,6 +324,7 @@ namespace Tasking Security *GetSecurityManager() { return &SecurityManager; } void CleanupProcessesThread(); void Panic() { StopScheduler = true; } + bool IsPanic() { return StopScheduler; } __always_inline inline void Schedule() { #if defined(a86) @@ -301,16 +337,16 @@ namespace Tasking void RevertProcessCreation(PCB *Process); void RevertThreadCreation(TCB *Thread); - void KillThread(TCB *tcb, int Code) + void KillThread(TCB *tcb, enum KillErrorCodes Code) { tcb->Status = TaskStatus::Terminated; - tcb->ExitCode = Code; + tcb->ExitCode = (int)Code; } - void KillProcess(PCB *pcb, int Code) + void KillProcess(PCB *pcb, enum KillErrorCodes Code) { pcb->Status = TaskStatus::Terminated; - pcb->ExitCode = Code; + pcb->ExitCode = (int)Code; } /** @@ -325,9 +361,9 @@ namespace Tasking */ TCB *GetCurrentThread(); - PCB *GetProcessByID(UPID ID); + PCB *GetProcessByID(PID ID); - TCB *GetThreadByID(UTID ID); + TCB *GetThreadByID(TID ID); /** @brief Wait for process to terminate */ void WaitForProcess(PCB *pcb); @@ -356,7 +392,6 @@ namespace Tasking const char **argv = nullptr, const char **envp = nullptr, const std::vector &auxv = std::vector(), - IPOffset Offset = 0, TaskArchitecture Architecture = TaskArchitecture::x64, TaskCompatibility Compatibility = TaskCompatibility::Native, bool ThreadNotReady = false); diff --git a/include/types.h b/include/types.h index 53a27ce..5a8f2b2 100644 --- a/include/types.h +++ b/include/types.h @@ -78,8 +78,19 @@ typedef __builtin_va_list va_list; #define offsetof(type, member) __builtin_offsetof(type, member) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MAX(a, b) \ + ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + }) + +#define MIN(a, b) \ + ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; \ + }) #define ROUND_UP(x, y) (((x) + (y)-1) & ~((y)-1)) #define ROUND_DOWN(x, y) ((x) & ~((y)-1)) @@ -183,6 +194,9 @@ typedef __SIG_ATOMIC_TYPE__ sig_atomic_t; // TODO: ssize_t typedef intptr_t ssize_t; +typedef long off_t; +typedef long long off64_t; + #define INT8_MAX __INT8_MAX__ #define INT8_MIN (-INT8_MAX - 1) #define UINT8_MAX __UINT8_MAX__ @@ -359,6 +373,9 @@ typedef uint48_t uint_fast48_t; #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) +#define PUBLIC __visibility("default") +#define PRIVATE __visibility("hidden") + #define SafeFunction __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_address_safety_analysis __no_sanitize_thread #define NIF __no_instrument_function diff --git a/include_std/cxxabi.h b/include_std/cxxabi.h new file mode 100644 index 0000000..178e145 --- /dev/null +++ b/include_std/cxxabi.h @@ -0,0 +1,69 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_CXXABI_H__ +#define __FENNIX_KERNEL_CXXABI_H__ + +#include +#include +#include + +namespace __cxxabiv1 +{ +#define ATEXIT_MAX_FUNCS 128 + + typedef unsigned uarch_t; + + struct atexit_func_entry_t + { + void (*destructor_func)(void *); + void *obj_ptr; + void *dso_handle; + }; + + struct __cxa_exception + { + std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + std::terminate_handler unexpectedHandler; + std::terminate_handler terminateHandler; + __cxa_exception *nextException; + int handlerCount; +#ifdef __ARM_EABI_UNWINDER__ + __cxa_exception *nextPropagatingException; + int propagationCount; +#else + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + _Unwind_Ptr catchTemp; + void *adjustedPtr; +#endif + _Unwind_Exception unwindHeader; + }; +} + +struct __cxa_eh_globals +{ + __cxxabiv1::__cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +#ifdef __ARM_EABI_UNWINDER__ + __cxxabiv1::__cxa_exception *propagatingExceptions; +#endif +}; + +#endif // !__FENNIX_KERNEL_CXXABI_H__ diff --git a/include_std/exception b/include_std/exception new file mode 100644 index 0000000..7544596 --- /dev/null +++ b/include_std/exception @@ -0,0 +1,41 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_EXCEPTION_H__ +#define __FENNIX_KERNEL_EXCEPTION_H__ + +#include + +namespace std +{ + class exception + { + public: + exception() noexcept {} + virtual ~exception() noexcept; + exception(const exception &) = default; + exception &operator=(const exception &) = default; + exception(exception &&) = default; + exception &operator=(exception &&) = default; + + virtual const char *what() const noexcept; + }; + + typedef void (*terminate_handler)(); +} + +#endif // !__FENNIX_KERNEL_EXCEPTION_H__ diff --git a/include_std/std/vector.hpp b/include_std/std/vector.hpp index 911ec60..cc9f7e2 100644 --- a/include_std/std/vector.hpp +++ b/include_std/std/vector.hpp @@ -123,7 +123,7 @@ namespace std NIF T &null_elem() { - static T null_elem; + static T null_elem{}; return null_elem; } diff --git a/include_std/stdarg.h b/include_std/stdarg.h new file mode 100644 index 0000000..714a590 --- /dev/null +++ b/include_std/stdarg.h @@ -0,0 +1,25 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_STDARG_H__ +#define __FENNIX_KERNEL_STDARG_H__ + +#include + + + +#endif // !__FENNIX_KERNEL_STDARG_H__ diff --git a/include_std/stdlib.h b/include_std/stdlib.h index 01bfa10..3d95cab 100644 --- a/include_std/stdlib.h +++ b/include_std/stdlib.h @@ -18,18 +18,4 @@ #ifndef _STDLIB_H #define _STDLIB_H -#ifdef __cplusplus -extern "C" -{ -#endif - - void *malloc(__SIZE_TYPE__ Size); - void *calloc(__SIZE_TYPE__ n, __SIZE_TYPE__ Size); - void *realloc(void *Address, __SIZE_TYPE__ Size); - void free(void *Address); - -#ifdef __cplusplus -} -#endif - #endif // !_STDLIB_H diff --git a/include_std/typeinfo b/include_std/typeinfo new file mode 100644 index 0000000..9bb9ee5 --- /dev/null +++ b/include_std/typeinfo @@ -0,0 +1,337 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_TYPEINFO_H__ +#define __FENNIX_KERNEL_TYPEINFO_H__ + +#include +#include + +namespace __cxxabiv1 +{ + class __class_type_info; + class __si_class_type_info; +} + +namespace std +{ + class type_info + { + public: + virtual ~type_info(); + + bool operator==(const type_info &Argument) const noexcept + { + return ((Name == Argument.Name) || + (Name[0] != '*' && + __builtin_strcmp(Name, Argument.Name) == 0)); + } + + bool operator!=(const type_info &Argument) const noexcept + { + return !operator==(Argument); + } + + bool before(const type_info &Argument) const noexcept + { + return (Name[0] == '*' && Argument.Name[0] == '*') + ? Name < Argument.Name + : __builtin_strcmp(Name, Argument.Name) < 0; + } + + const char *name() const noexcept + { + return Name[0] == '*' ? Name + 1 : Name; + } + + virtual bool __is_pointer_p() const + { + return Name[0] == '*'; + } + + virtual bool __is_function_p() const + { + return Name[0] == '('; + } + + virtual bool __do_catch(const type_info *ThrowType, + void **ThrowObject, + unsigned Outer) const; + + virtual bool __do_upcast(const __cxxabiv1::__class_type_info *Target, + void **ObjectPointer) const; + + protected: + const char *Name; + explicit type_info(const char *n) : Name(n) {} + + private: + type_info &operator=(const type_info &); + type_info(const type_info &); + }; + + class bad_cast : public exception + { + public: + bad_cast() noexcept {} + virtual ~bad_cast() noexcept; + virtual const char *what() const noexcept; + }; + + class bad_typeid : public exception + { + public: + bad_typeid() noexcept {} + virtual ~bad_typeid() noexcept; + virtual const char *what() const noexcept; + }; +} + +namespace __cxxabiv1 +{ + class __pbase_type_info : public std::type_info + { + public: + unsigned int Flags; + const std::type_info *Pointee; + + explicit __pbase_type_info(const char *n, int Qualifiers, + const std::type_info *Type) + : std::type_info(n), + Flags(Qualifiers), + Pointee(Type) {} + virtual ~__pbase_type_info(); + + enum __masks + { + __const_mask = 0x1, + __volatile_mask = 0x2, + __restrict_mask = 0x4, + __incomplete_mask = 0x8, + __incomplete_class_mask = 0x10, + __transaction_safe_mask = 0x20, + __noexcept_mask = 0x40 + }; + + protected: + __pbase_type_info(const __pbase_type_info &); + + __pbase_type_info &operator=(const __pbase_type_info &); + + virtual bool __do_catch(const std::type_info *ThrowType, + void **ThrowObject, + unsigned int Outer) const; + + inline bool __pointer_catch(const __pbase_type_info *ThrownType, + void **ThrowObject, + unsigned Outer) const + { + return Pointee->__do_catch(ThrownType->Pointee, ThrowObject, Outer + 2); + } + }; + + class __pointer_type_info : public __pbase_type_info + { + public: + explicit __pointer_type_info(const char *n, + int Qualifiers, + const std::type_info *Type) + : __pbase_type_info(n, Qualifiers, Type) {} + virtual ~__pointer_type_info(); + + protected: + virtual bool __is_pointer_p() const; + + virtual bool __pointer_catch(const __pbase_type_info *ThrowType, + void **ThrowObject, + unsigned Outer) const; + }; + + /* FIXME: stub */ + class __pointer_to_member_type_info : public __pbase_type_info + { + }; + + class __fundamental_type_info : public std::type_info + { + public: + explicit __fundamental_type_info(const char *n) : std::type_info(n) {} + virtual ~__fundamental_type_info(); + }; + + class __base_class_type_info + { + public: + const __class_type_info *BaseType; +#ifdef __LP64__ + long long OffsetFlags; +#else + long OffsetFlags; +#endif + + enum __offset_flags_masks + { + __virtual_mask = 0x1, + __public_mask = 0x2, + __hwm_bit = 0x2, + __offset_shift = 0x8 + }; + + bool __is_virtual_p() const + { + return OffsetFlags & __virtual_mask; + } + + bool __is_public_p() const + { + return OffsetFlags & __public_mask; + } + + ptrdiff_t __offset() const + { + return static_cast(OffsetFlags) >> __offset_shift; + } + }; + + /* FIXME: stub */ + class __vmi_class_type_info /* : public __class_type_info */ + { + public: + enum __flags_masks + { + __non_diamond_repeat_mask = 0x1, + __diamond_shaped_mask = 0x2, + __flags_unknown_mask = 0x10 + }; + }; + + class __class_type_info : public std::type_info + { + public: + explicit __class_type_info(const char *n) + : std::type_info(n) {} + virtual ~__class_type_info(); + + enum __sub_kind + { + __unknown = 0, + __not_contained, + __contained_ambig, + __contained_virtual_mask = __base_class_type_info::__virtual_mask, + __contained_public_mask = __base_class_type_info::__public_mask, + __contained_mask = 1 << __base_class_type_info::__hwm_bit, + __contained_private = __contained_mask, + __contained_public = __contained_mask | __contained_public_mask + }; + + struct __upcast_result + { + const void *dst_ptr; + __sub_kind part2dst; + int src_details; + const __class_type_info *base_type; + + __upcast_result(int d) + : dst_ptr(NULL), + part2dst(__unknown), + src_details(d), + base_type(NULL) {} + }; + + struct __dyncast_result + { + const void *dst_ptr; + __sub_kind whole2dst; + __sub_kind whole2src; + __sub_kind dst2src; + int whole_details; + + __dyncast_result(int details_ = __vmi_class_type_info::__flags_unknown_mask) + : dst_ptr(NULL), + whole2dst(__unknown), + whole2src(__unknown), + dst2src(__unknown), + whole_details(details_) {} + + protected: + __dyncast_result(const __dyncast_result &); + + __dyncast_result & + operator=(const __dyncast_result &); + }; + + virtual __sub_kind __do_find_public_src(ptrdiff_t SourceToDestination, + const void *ObjectPointer, + const __class_type_info *SourceType, + const void *SubroutinePointer) const; + + virtual bool __do_upcast(const __class_type_info *Destination, + const void *Object, + __upcast_result &__restrict Result) const; + + virtual bool __do_dyncast(ptrdiff_t SourceToDestination, + __sub_kind AccessPath, + const __class_type_info *DestinationType, + const void *ObjectPointer, + const __class_type_info *SourceType, + const void *SourcePointer, + __dyncast_result &Result) const; + + protected: + virtual bool __do_upcast(const __class_type_info *DestinationType, + void **ObjectPointer) const; + + virtual bool __do_catch(const type_info *ThrowType, + void **ThrowObject, + unsigned Outer) const; + }; + + class __si_class_type_info : public __class_type_info + { + public: + const __class_type_info *BaseType; + + explicit __si_class_type_info(const char *n, + const __class_type_info *Base) + : __class_type_info(n), + BaseType(Base) {} + virtual ~__si_class_type_info(); + + protected: + __si_class_type_info(const __si_class_type_info &); + + __si_class_type_info &operator=(const __si_class_type_info &); + + virtual bool __do_dyncast(ptrdiff_t SourceToDestination, __sub_kind AccessPath, + const __class_type_info *DestinationType, const void *ObjectPointer, + const __class_type_info *SourceType, const void *SourcePointer, + __dyncast_result &Result) const; + + virtual __sub_kind __do_find_public_src(ptrdiff_t SourceToDestination, + const void *ObjectPointer, + const __class_type_info *SourceType, + const void *SubroutinePointer) const; + + virtual bool __do_upcast(const __class_type_info *Destination, + const void *Object, + __upcast_result &__restrict Result) const; + }; + + static const __class_type_info *const nonvirtual_base_type = static_cast(0) + 1; +} + +#endif // !__FENNIX_KERNEL_TYPEINFO_H__ diff --git a/include_std/unwind.h b/include_std/unwind.h new file mode 100644 index 0000000..d46b2f2 --- /dev/null +++ b/include_std/unwind.h @@ -0,0 +1,78 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_UNWIND_H__ +#define __FENNIX_KERNEL_UNWIND_H__ + +#include + +enum _Unwind_Reason_Code +{ + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 +}; + +typedef void *_Unwind_Context_Reg_Val; +typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__))); +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); +typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__))); +typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__))); +typedef int _Unwind_Action; + +enum _UA : _Unwind_Action +{ + _UA_SEARCH_PHASE = 1, + _UA_CLEANUP_PHASE = 2, + _UA_HANDLER_FRAME = 4, + _UA_FORCE_UNWIND = 8, + _UA_END_OF_STACK = 16 +}; + +typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code, + struct _Unwind_Exception *); + +typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int, + _Unwind_Action, + _Unwind_Exception_Class, + struct _Unwind_Exception *, + struct _Unwind_Context *); + +struct _Unwind_Exception +{ + _Unwind_Exception_Class exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + _Unwind_Word private_1; + _Unwind_Word private_2; +} __attribute__((__aligned__)); + +struct _Unwind_Context; + +struct _Unwind_FrameState +{ + _Unwind_Personality_Fn personality; +}; + +EXTERNC _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *Exception); + +#endif // !__FENNIX_KERNEL_UNWIND_H__ diff --git a/kernel.h b/kernel.h index e9f482c..139564b 100644 --- a/kernel.h +++ b/kernel.h @@ -62,6 +62,7 @@ extern Recovery::KernelRecovery *RecoveryScreen; extern VirtualFileSystem::Node *DevFS; extern VirtualFileSystem::Node *MntFS; extern VirtualFileSystem::Node *ProcFS; +extern VirtualFileSystem::Node *VarLogFS; #endif // __cplusplus diff --git a/syscalls.h b/syscalls.h index e6687fa..179372f 100644 --- a/syscalls.h +++ b/syscalls.h @@ -35,12 +35,75 @@ #include +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +enum MemoryMapFlags +{ + MAP_PRESENT = 1 << 0, + MAP_WRITABLE = 1 << 1, + MAP_USER = 1 << 2, +}; + +enum KCtl +{ + KCTL_NULL, + + KCTL_GET_PID, + KCTL_GET_TID, + KCTL_GET_UID, + KCTL_GET_GID, + + /** + * @brief Get the page size + */ + KCTL_GET_PAGE_SIZE, + + /** + * @brief Check whether the current thread is critical + */ + KCTL_IS_CRITICAL, + + /** + * @brief Register an ELF library + * @fn int RegisterELFLib(char *Identifier, char *Path) + */ + KCTL_REGISTER_ELF_LIB, + + /** + * @brief Get an ELF library + * @fn uintptr_t GetELFLib(char *Identifier); + */ + KCTL_GET_ELF_LIB_MEMORY_IMAGE, + + /** + * @brief Get the absolute path of a library file + * @fn int GetAbsolutePath(char *Identifier, char *Buffer, size_t BufferSize) + */ + KCTL_GET_ABSOLUTE_PATH, +}; + /** * @enum NativeSyscalls * Enumeration of all the native syscalls available in the kernel */ enum NativeSyscalls { + /** + * + * Basic syscalls + * + */ + /** @brief Exit the process. * @fn int Exit(int Code) * This syscall is used to exit the current process with the provided exit code. @@ -53,6 +116,12 @@ enum NativeSyscalls */ _Print, + /** + * + * Memory syscalls + * + */ + /** @brief Request pages of memory * @fn uintptr_t RequestPages(size_t Count) * This syscall is used to request a specific number of pages of memory from the kernel. @@ -71,6 +140,29 @@ enum NativeSyscalls */ _DetachAddress, + /** + * @brief Map memory address + * @fn int MapAddress(uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags) + * This syscall is used to map a specific memory address to the current process. + * + * @param Size The size of the memory region to map. Not pages. + */ + _MemoryMap, + + /** @brief Unmap memory address + * @fn int UnmapAddress(uintptr_t VirtualAddress, size_t Size) + * This syscall is used to unmap a specific memory address from the current process. + * + * @param Size The size of the memory region to unmap. Not pages. + */ + _MemoryUnmap, + + /** + * + * Kernel Control syscalls + * + */ + /** @brief Kernel Control * @fn uintptr_t KernelCTL(enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) * This syscall is used to control certain aspects of the kernel or get information about it. @@ -78,11 +170,10 @@ enum NativeSyscalls _KernelCTL, /** - * @brief Creates/Reads/Writes/Deletes an IPC Pipe/Shared Memory/Message Queue/etc. - * @fn int IPC(enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size) - * This syscall is used to create, read, write or delete an IPC Pipe/Shared Memory/Message Queue/etc. + * + * File syscalls + * */ - _IPC, /** @brief Open a file * @fn void *FileOpen(const char *Path, uint64_t Flags) @@ -97,19 +188,19 @@ enum NativeSyscalls _FileClose, /** @brief Read from a file - * @fn uint64_t FileRead(void *KernelPrivate, uint64_t Offset, uint8_t *Buffer, uint64_t Size) + * @fn uint64_t FileRead(void *KernelPrivate, uint8_t *Buffer, uint64_t Size) * This syscall is used to read a specific number of bytes from a file at a specific offset. */ _FileRead, /** @brief Write to a file - * @fn uint64_t FileWrite(void *KernelPrivate, uint64_t Offset, uint8_t *Buffer, uint64_t Size) + * @fn uint64_t FileWrite(void *KernelPrivate, uint8_t *Buffer, uint64_t Size) * This syscall is used to write a specific number of bytes to a file at a specific offset. */ _FileWrite, /** @brief Seek in a file - * @fn uint64_t FileSeek(void *KernelPrivate, uint64_t Offset, int Whence) + * @fn off_t FileSeek(void *KernelPrivate, off_t Offset, int Whence) * This syscall is used to change the current offset in a file. */ _FileSeek, @@ -120,6 +211,19 @@ enum NativeSyscalls */ _FileStatus, + /** + * + * Process syscalls + * + */ + + /** + * @brief Creates/Reads/Writes/Deletes an IPC Pipe/Shared Memory/Message Queue/etc. + * @fn int IPC(enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size) + * This syscall is used to create, read, write or delete an IPC Pipe/Shared Memory/Message Queue/etc. + */ + _IPC, + /** @brief Sleep for a specific amount of time * @fn int Sleep(uint64_t Milliseconds) * This syscall is used to sleep the current thread for a specific amount of time. @@ -215,6 +319,9 @@ enum NativeSyscalls /** @brief Reserved syscall */ _SysReservedCreateThread, + + /** @brief Not a real syscall */ + _MaxSyscall }; /**