From: Amelia Coutard Date: Fri, 29 Dec 2023 03:29:14 +0000 (+0100) Subject: Remplacement de os::assert par une macro assert dans la "librairie standard" X-Git-Url: https://git.ameliathe1st.gay/?a=commitdiff_plain;h=027ab6719a30395276053f545d72a42308d1b15e;p=voyage-au-centre-des-fichiers.git Remplacement de os::assert par une macro assert dans la "librairie standard" --- diff --git a/kernel/src/elf64.cpp b/kernel/src/elf64.cpp index d5df9d9..9ced6fb 100644 --- a/kernel/src/elf64.cpp +++ b/kernel/src/elf64.cpp @@ -12,29 +12,30 @@ // not, see . #include "elf64.hpp" +#include void os::elf::load_elf(os::process& result, amy::byte* start, amy::size length, const paging::PML4T& original_PML4T) { - os::assert(length >= amy::byte_size(), "Elf file isn't big enough to contain a header: there is an error."); + assert(length >= amy::byte_size(), "Elf file isn't big enough to contain a header: there is an error."); // TODO: Check that the elf file sections are all fully inside the file. // Load test-module elf file: const os::elf::header elf_header = *(os::elf::header*)start; // Check if elf is valid: - os::assert(elf_header.magic[0] == '\x7f', "No elf header."); - os::assert(elf_header.magic[1] == 'E', "No elf header."); - os::assert(elf_header.magic[2] == 'L', "No elf header."); - os::assert(elf_header.magic[3] == 'F', "No elf header."); - os::assert(elf_header.bitn == 2, "Elf file not 64 bits."); - os::assert(elf_header.endianness == 1, "Elf file not little endian."); - os::assert(elf_header.type == 2, "Elf file not executable."); - os::assert(elf_header.arch == 0x3E, "Elf file not x86_64."); + assert(elf_header.magic[0] == '\x7f', "No elf header."); + assert(elf_header.magic[1] == 'E', "No elf header."); + assert(elf_header.magic[2] == 'L', "No elf header."); + assert(elf_header.magic[3] == 'F', "No elf header."); + assert(elf_header.bitn == 2, "Elf file not 64 bits."); + assert(elf_header.endianness == 1, "Elf file not little endian."); + assert(elf_header.type == 2, "Elf file not executable."); + assert(elf_header.arch == 0x3E, "Elf file not x86_64."); constexpr amy::size stack_size = 16 * 0x1000 /* 64KiB */; amy::byte* const stack = (amy::byte*)0x0000'8000'0000'0000 - stack_size; const auto page = os::paging::page_allocator.allocate(1); - os::assert(page.ptr != nullptr, "Not enough memory for elf file loading."); + assert(page.ptr != amy::nil, "Not enough memory for elf file loading."); result.PML4T = phys_ptr(page.ptr.get_phys_addr()); result.rip = amy::u64(elf_header.entry); result.rsp = amy::u64(stack + stack_size); @@ -68,7 +69,7 @@ void os::elf::load_elf(os::process& result, amy::byte* start, amy::size length, continue; } os::print("Segment: loadable\n"); - os::assert(0x1000 <= amy::u64(program_header.p_vaddr) + assert(0x1000 <= amy::u64(program_header.p_vaddr) && amy::u64(program_header.p_vaddr + program_header.p_memsz) < 0x10'0000'0000, "Program segments must be contained between 0x1000 and 0x10'0000'0000 (i.e. 64GiB)."); @@ -76,7 +77,7 @@ void os::elf::load_elf(os::process& result, amy::byte* start, amy::size length, amy::size nb_pages = (amy::u64(program_header.p_vaddr) % 0x1000 + program_header.p_memsz + 0x1000 - 1) / 0x1000; for (amy::size i = 0; i < nb_pages; i++) { auto const alloc = os::paging::page_allocator.allocate(1); - os::assert(alloc.ptr != nullptr, "Failed to allocate enough memory for loading of elf binary."); + assert(alloc.ptr != nullptr, "Failed to allocate enough memory for loading of elf binary."); os::paging::map_page(*result.PML4T, (os::paging::page<0>*)(program_header.p_vaddr + i * 0x1000), alloc.ptr, { .RW = ((program_header.flags & 2) >> 1) != 0, .US = true, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = false, .AVL = 0, diff --git a/kernel/src/interrupts.cpp b/kernel/src/interrupts.cpp index 2288039..3b7d9ef 100644 --- a/kernel/src/interrupts.cpp +++ b/kernel/src/interrupts.cpp @@ -112,7 +112,7 @@ extern "C" void int_page_fault(amy::u32 err_code, amy::u64 vaddr) { ) { // Kernel memory os::print("Allocating (Ring 0): {}\n", (void*)vaddr); auto const alloc = os::paging::page_allocator.allocate(1); - os::assert(alloc.ptr != nullptr, "Out of memory."); + assert(alloc.ptr != nullptr, "Out of memory."); os::paging::map_page(os::paging::global_PML4T, (os::paging::page<0>*)vaddr, alloc.ptr, {.RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = true}); return; @@ -121,7 +121,7 @@ extern "C" void int_page_fault(amy::u32 err_code, amy::u64 vaddr) { ) { // Userspace memory os::print("Allocating (Ring 3): {}\n", (void*)vaddr); auto const alloc = os::paging::page_allocator.allocate(1); - os::assert(alloc.ptr != nullptr, "Out of memory."); + assert(alloc.ptr != nullptr, "Out of memory."); os::paging::map_page(*os::get_process(os::current_pid).PML4T, (os::paging::page<0>*)vaddr, alloc.ptr, {.RW = true, .US = true, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = false, .AVL = 0, .NX = true}); return; diff --git a/kernel/src/interrupts.hpp b/kernel/src/interrupts.hpp index 1ea335f..846168f 100644 --- a/kernel/src/interrupts.hpp +++ b/kernel/src/interrupts.hpp @@ -14,6 +14,7 @@ #pragma once #include +#include #include "lib/phys_ptr.hpp" #include "serial.hpp" #include "utils.hpp" @@ -58,12 +59,9 @@ struct isr_info { bool present : 1 = true; }; -template -void assert(bool cond, const char* format, const Ts&... vs); - template void enable_interrupts(const isr_info (&ISRs)[interrupt_nb], os::idt& idt) { - os::assert(is_APIC_builtin(), "No builtin APIC."); + assert(is_APIC_builtin(), "No builtin APIC."); disable_PIC(); set_APIC_reg(0xF0, 0x1FF); // Enable APIC diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index 42d0355..76dcd4a 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "lib/multiboot2.hpp" #include "paging.hpp" #include "utils.hpp" @@ -37,18 +38,18 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr>(amy::ptr(&bootstrap_pages_for_memory) & amy::ptr(~0xFFFF'FFFF'8000'0000)), .size = amy::byte_size() / amy::byte_size() }); - os::assert(os::cpu_has_msr(), "MSRs aren't supported."); + assert(os::cpu_has_msr(), "MSRs aren't supported."); // Initialise kernel map. - os::assert(amy::ptr(&_kernel_phys_start) % 4096 == 0, "Kernel isn't page aligned !"); - os::assert(amy::ptr(&_kernel_phys_rw_start) % 4096 == 0, "Kernel isn't page aligned !"); - os::assert(amy::ptr(&_kernel_phys_end) % 4096 == 0, "Kernel isn't page aligned !"); + assert(amy::ptr(&_kernel_phys_start) % 4096 == 0, "Kernel isn't page aligned !"); + assert(amy::ptr(&_kernel_phys_rw_start) % 4096 == 0, "Kernel isn't page aligned !"); + assert(amy::ptr(&_kernel_phys_end) % 4096 == 0, "Kernel isn't page aligned !"); for (amy::size i = amy::ptr(&_kernel_phys_start); i < amy::ptr(&_kernel_phys_rw_start); ) { if (i % (1024 * 1024 * 1024) == 0 && i + 1024 * 1024 * 1024 < amy::ptr(&_kernel_phys_rw_start)) { os::paging::map_page<2, 3>(os::paging::global_PML4T, (os::paging::page<2>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr>(i), @@ -94,8 +95,8 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr( @@ -193,7 +194,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr() * 64, amy::byte_align()> available_ram_allocator; amy::vector available_ram(available_ram_allocator); - os::assert(!available_ram.construction_failed(), "Failed to create vector."); + assert(!available_ram.construction_failed(), "Failed to create vector."); amy::size available_ram_length = 0; bool module_specified = false; @@ -215,7 +216,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr> kernel_s{amy::ptr(&_kernel_phys_start)}; @@ -250,7 +251,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr #include +#include namespace os { @@ -28,9 +29,11 @@ public: constexpr phys_ptr(amy::nil_t): phys_addr(0xF000'0000'0000'0000) {} inline void* operator->() const { + assert(*this != amy::nil); return get_virt_addr(); } inline explicit operator void*() const { + assert(*this != amy::nil); return get_virt_addr(); } @@ -60,12 +63,15 @@ public: constexpr phys_ptr(amy::nil_t): phys_addr(0xF000'0000'0000'0000) {} T& operator[](amy::diff i) const { + assert(*this != amy::nil); return get_virt_addr()[i]; } T& operator*() const { + assert(*this != amy::nil); return *get_virt_addr(); } T* operator->() const { + assert(*this != amy::nil); return get_virt_addr(); } explicit operator T*() const { diff --git a/kernel/src/paging.hpp b/kernel/src/paging.hpp index ede7e3b..67df518 100644 --- a/kernel/src/paging.hpp +++ b/kernel/src/paging.hpp @@ -13,10 +13,11 @@ #pragma once +#include #include +#include "lib/phys_ptr.hpp" #include "serial.hpp" #include "utils.hpp" -#include "lib/phys_ptr.hpp" namespace os { namespace paging { @@ -53,12 +54,12 @@ template struct paging_entry { return (data & (1 << 0)) != 0; } bool is_page() { - os::assert(is_present(), "Cannot check if a paging_entry is a page if it's not present."); + assert(is_present(), "Cannot check if a paging_entry is a page if it's not present."); return depth == 0 || (data & (1 << 7)) != 0; } paging::page_info page_info() { - os::assert(is_page(), "Cannot access page info for a non-page."); + assert(is_page(), "Cannot access page info for a non-page."); return { .RW = (data & (1ull << 1)) != 0, .US = (data & (1ull << 2)) != 0, @@ -76,12 +77,12 @@ template struct paging_entry { }; } os::phys_ptr> page_ptr() { - os::assert(is_page(), "Cannot access page physical pointer for a non-page."); + assert(is_page(), "Cannot access page physical pointer for a non-page."); amy::ptr addr = data & (depth == 0 ? 0x0000'FFFF'FFFF'F000 : 0x0000'FFFF'FFFF'E000); return os::phys_ptr>(addr | ((addr & 0x0000'8000'0000'0000) != 0 ? 0xFFFF'8000'0000'0000 : 0)); } void page_ptr(os::phys_ptr> page) { - os::assert(is_page(), "Cannot access page physical pointer for a non-page."); + assert(is_page(), "Cannot access page physical pointer for a non-page."); if (depth == 0) { data = (data & ~0x0000'FFFF'FFFF'F000) | page.get_phys_addr(); } else { @@ -89,7 +90,7 @@ template struct paging_entry { } } paging::paging_table_info paging_table_info() { - os::assert(!is_page(), "Cannot access paging table info for a page."); + assert(!is_page(), "Cannot access paging table info for a page."); return { .RW = (data & (1ull << 1)) != 0, .US = (data & (1ull << 2)) != 0, @@ -103,12 +104,12 @@ template struct paging_entry { }; } os::phys_ptr> paging_table_ptr() { - os::assert(!is_page(), "Cannot access paging table physical pointer for a page."); + assert(!is_page(), "Cannot access paging table physical pointer for a page."); amy::ptr addr = data & 0x0000'FFFF'FFFF'F000; return os::phys_ptr>(addr | ((addr & 0x0000'8000'0000'0000) != 0 ? 0xFFFF'8000'0000'0000 : 0)); } void paging_table_ptr(os::phys_ptr> table) { - os::assert(!is_page(), "Cannot access paging table physical pointer for a page."); + assert(!is_page(), "Cannot access paging table physical pointer for a page."); data = (data & ~0x0000'FFFF'FFFF'F000) | table.get_phys_addr(); } void remove() { @@ -220,7 +221,7 @@ template void map_page(paging_table& paging_table, page const* vaddr, phys_ptr> paddr, os::paging::page_info page_info) { amy::size const index = (amy::ptr(vaddr) >> (12 + 9 * paging_depth)) & 0x1FF; if constexpr (depth == paging_depth) { - os::assert(!paging_table.contents[index].is_present(), "Virtual address 0x{} is already mapped.", vaddr); + assert(!paging_table.contents[index].is_present(), "Virtual address 0x{} is already mapped.", vaddr); paging_table.contents[index].page_info(page_info); paging_table.contents[index].page_ptr(paddr); invlpg(vaddr); diff --git a/kernel/src/ring3.cpp b/kernel/src/ring3.cpp index 5df22c5..f0716d5 100644 --- a/kernel/src/ring3.cpp +++ b/kernel/src/ring3.cpp @@ -11,6 +11,7 @@ // You should have received a copy of the GNU General Public License along with this program. If // not, see . +#include #include "ring3.hpp" #include "utils.hpp" #include "serial.hpp" @@ -51,19 +52,19 @@ void schedule_next_process() { // extern "C" int os::syscall_mount_kernel_device(amy::fd wd, char device, char const* path, amy::size path_len, int mount_type); extern "C" int os::syscall_mount_kernel_device(amy::fd, char, char const*, amy::size, int) { - os::assert(false, "mount_kernel_device not implemented yet."); + assert(false, "mount_kernel_device not implemented yet."); __builtin_unreachable(); } // extern "C" amy::fd os::syscall_open(amy::fd wd, char const* path, amy::size path_len, int options); extern "C" amy::fd os::syscall_open(amy::fd, char const*, amy::size, int) { - os::assert(false, "open not implemented yet."); + assert(false, "open not implemented yet."); __builtin_unreachable(); } extern "C" amy::size os::syscall_read(amy::fd file, char* data, amy::size len) { - os::assert(file == amy::fd(0), "Read isn't really implemented for now."); - os::assert(len >= 0, "Read expects a positive size."); + assert(file == amy::fd(0), "Read isn't really implemented for now."); + assert(len >= 0, "Read expects a positive size."); if (len == 0) { return 0; } @@ -82,8 +83,8 @@ extern "C" amy::size os::syscall_read(amy::fd file, char* data, amy::size len) { } extern "C" amy::size os::syscall_write(amy::fd file, char const* data, amy::size len) { - os::assert(file == amy::fd(0), "Write isn't really implemented for now."); - os::assert(len >= 0, "Write expects a positive size."); + assert(file == amy::fd(0), "Write isn't really implemented for now."); + assert(len >= 0, "Write expects a positive size."); if (len == 0) { return 0; } @@ -99,12 +100,12 @@ extern "C" amy::size os::syscall_write(amy::fd file, char const* data, amy::size // extern "C" int syscall_close(amy::fd file); extern "C" int os::syscall_close(amy::fd) { - os::assert(false, "Close isn't implemented for now."); + assert(false, "Close isn't implemented for now."); __builtin_unreachable(); } extern "C" void os::syscall_rax_error_handler() { - os::assert(false, "Incorrect %rax for syscall."); + assert(false, "Incorrect %rax for syscall."); __builtin_unreachable(); } diff --git a/kernel/src/serial.cpp b/kernel/src/serial.cpp index 5f2f58a..2bd0477 100644 --- a/kernel/src/serial.cpp +++ b/kernel/src/serial.cpp @@ -15,6 +15,13 @@ #include "interrupts.hpp" #include "serial.hpp" +void amy::assert_handler(char const* cond, char const* file, int line) { + os::print("Assertion error in file '{}', at line {}: {}.\n", file, (unsigned)line, cond); + while (true) { + os::hlt(); + } +} + bool os::init_serial_port() { outb(serial_port + 1, 0x00); // Disable interrupts. outb(serial_port + 3, 0x80); // Prepare to set baud rate divisor (38400 baud). @@ -52,13 +59,13 @@ void os::printc(char c) { write_serial(c); } void os::print_formatted(const char* format, const char* val) { - os::assert(format[0] == '}', "Format string unsupported. TODO."); + assert(format[0] == '}', "Format string unsupported. TODO."); for (amy::size i = 0; val[i] != '\0'; i++) { os::printc(val[i]); } } void os::print_formatted(const char* format, amy::u64 val) { - os::assert(format[0] == '}', "Format string unsupported. TODO."); + assert(format[0] == '}', "Format string unsupported. TODO."); char data[20]; char* curr = data + 19; while (val != 0) { @@ -74,7 +81,7 @@ void os::print_formatted(const char* format, amy::u64 val) { } } void os::print_formatted(const char* format, amy::i64 val) { - os::assert(format[0] == '}', "Format string unsupported. TODO."); + assert(format[0] == '}', "Format string unsupported. TODO."); if (val < 0) { os::printc('-'); os::print_formatted(format, amy::u64(-val)); @@ -84,7 +91,7 @@ void os::print_formatted(const char* format, amy::i64 val) { } } void os::print_formatted(const char* format, phys_ptr val) { - os::assert(format[0] == '}', "Format string unsupported. TODO."); + assert(format[0] == '}', "Format string unsupported. TODO."); os::print("0x"); for (int i = 60; i >= 0; i -= 4) { const int v = (val.get_phys_addr() >> i) & 0xF; @@ -92,7 +99,7 @@ void os::print_formatted(const char* format, phys_ptr val) { } } void os::print_formatted(const char* format, const void* val) { - os::assert(format[0] == '}', "Format string unsupported. TODO."); + assert(format[0] == '}', "Format string unsupported. TODO."); os::print("0x"); for (int i = 60; i >= 0; i -= 4) { const int v = (reinterpret_cast(val) >> i) & 0xF; diff --git a/kernel/src/serial.hpp b/kernel/src/serial.hpp index 479f1f0..908ab50 100644 --- a/kernel/src/serial.hpp +++ b/kernel/src/serial.hpp @@ -13,14 +13,12 @@ #pragma once +#include #include "types.hpp" #include "lib/phys_ptr.hpp" namespace os { -template -void assert(bool cond, const char* format, const Ts&... vs); - constexpr amy::u16 serial_port{0x3F8}; bool init_serial_port(); @@ -72,24 +70,21 @@ void print(const char* format, const Ts&... vs) { for (amy::size i = 0; format[i] != '\0'; i++) { if (format[i] == '{') { i++; - if (format[i] == '\0') { - os::assert(false, "Error in format string: unterminated '{{}'."); - } else if (format[i] == '{') { + assert(format[i] != '\0', "Error in format string: unterminated '{{}'."); + if (format[i] == '{') { printc('{'); continue; } else { amy::size format_spec_end = i; while (format[format_spec_end] != '}') { - if (format[format_spec_end++] == '\0') { - os::assert(false, "Error in format string: unterminated '{{}'."); - } + assert(format[format_spec_end++] != '\0', "Error in format string: unterminated '{{}'."); } amy::size n = arg_n; if ('0' <= format[i] && format[i] <= '9') { if (arg_n == 0) { arg_n_is_given = true; } - os::assert(arg_n_is_given, "Error in format string: either the arg_id is always given, or never."); + assert(arg_n_is_given, "Error in format string: either the arg_id is always given, or never."); amy::size n_ = 0; while ('0' <= format[i] && format[i] <= '9') { n_ = n_ * 10 + (format[i++] - '0'); @@ -99,20 +94,20 @@ void print(const char* format, const Ts&... vs) { if (arg_n == 0) { arg_n_is_given = false; } - os::assert(!arg_n_is_given, "Error in format string: either the arg_id is always given, or never."); + assert(!arg_n_is_given, "Error in format string: either the arg_id is always given, or never."); } if (format[i] == ':') { i++; } else { - os::assert(format[i] == '}', "Error in format string: ':' required before format spec."); + assert(format[i] == '}', "Error in format string: ':' required before format spec."); } - os::assert(n < amy::size(sizeof...(vs)), "Error in format string: not enough arguments."); + assert(n < amy::size(sizeof...(vs)), "Error in format string: not enough arguments."); (print_nth_helper{n, &format[i]} % ... % get_more_general_type_helper_t(vs)); i = format_spec_end; arg_n++; } } else if (format[i] == '}') { - os::assert(format[i + 1] == '}', "Error in format string: unexpected '}'."); + assert(format[i + 1] == '}', "Error in format string: unexpected '}'."); i++; printc('}'); } else { @@ -124,15 +119,4 @@ void print(const char* format, const Ts&... vs) { void cli(); void hlt(); -template -void assert(bool cond, const char* format, const Ts&... vs) { - if (!cond) { - print("Error: "); - print(format, vs...); - printc('\n'); - cli(); - while (true) { hlt(); } - } -} - } // namespace os diff --git a/kernel/src/utils.hpp b/kernel/src/utils.hpp index 3ac872f..2381c04 100644 --- a/kernel/src/utils.hpp +++ b/kernel/src/utils.hpp @@ -13,6 +13,7 @@ #pragma once +#include #include #include #include "serial.hpp" @@ -51,22 +52,22 @@ public: return 0 <= index && index < n && elems[index].present; } amy::i64 create() { - os::assert(has_room(), "Too many allocated elems in incrementing_int64_map."); + assert(has_room(), "Too many allocated elems in incrementing_int64_map."); elems[n].present = true; new(elems[n].buffer) T; return n++; } void remove(amy::i64 index) { - os::assert(present(index), "Tried removing non-existant element of incrementing_int64_map."); + assert(present(index), "Tried removing non-existant element of incrementing_int64_map."); get(index).~T(); elems[index].present = false; } T& get(amy::i64 index) { - os::assert(present(index), "Tried getting non-existant element of incrementing_int64_map."); + assert(present(index), "Tried getting non-existant element of incrementing_int64_map."); return *amy::launder(reinterpret_cast(&elems[index].buffer[0])); } const T& get(amy::i64 index) const { - os::assert(present(index), "Tried getting non-existant element of incrementing_int64_map."); + assert(present(index), "Tried getting non-existant element of incrementing_int64_map."); return *amy::launder(reinterpret_cast(&elems[index].buffer[0])); } diff --git a/libcpp/assert.hpp b/libcpp/assert.hpp new file mode 100644 index 0000000..1e61440 --- /dev/null +++ b/libcpp/assert.hpp @@ -0,0 +1,20 @@ +// Copyright 2023 Amélia COUTARD. +// +// This file from the program "voyage au centre des fichiers" 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. +// +// This program 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 this program. If +// not, see . + +#pragma once + +#define assert(cond, ...) if (!(cond)) amy::assert_handler(#cond ", " #__VA_ARGS__, __FILE__, __LINE__) + +namespace amy { + void assert_handler(char const* cond, char const* file, int line) __attribute__((noreturn)); +} // namespace amy