diff --git a/api/arch/x86/paging.hpp b/api/arch/x86/paging.hpp index 47cfa9e15..2fa2fe784 100644 --- a/api/arch/x86/paging.hpp +++ b/api/arch/x86/paging.hpp @@ -317,7 +317,7 @@ class Page_table { auto* sub = page_dir(&ent); Expects(sub != nullptr); if (print) { - printf("%.*s-+<%s> 0x%zx\n", print_lvl * 2, pad, + printf("%.*s-+<%s> %p\n", print_lvl * 2, pad, util::Byte_r(page_size).to_string().c_str(), (void*)sub->start_addr()); } sum += sub->summary(print, print_lvl + 1); diff --git a/api/expects b/api/expects index dc106a9e0..9ff218539 100644 --- a/api/expects +++ b/api/expects @@ -32,28 +32,43 @@ #endif #include -inline void __expect_fail(const char *expr, const char *file, int line, const char *func){ +inline void __expect_emit_failure(std::string_view msg, std::string_view panic_text) { #ifndef UNITTESTS #ifdef INCLUDEOS_SMP_ENABLE SMP::global_lock(); #endif - fprintf(stderr, "%s:%i:%s %s \n",file, line, func, expr); + std::fprintf(stderr, "%.*s\n", int(msg.size()), msg.data()); fflush(NULL); #ifdef INCLUDEOS_SMP_ENABLE SMP::global_unlock(); #endif - os::panic(expr); + os::panic(std::string(panic_text).c_str()); #else // TEST + (void) panic_text; // throw here to allow tests to capture the error #include - #include - auto msg = std::format("{}:{}:{} {}",file, line, func, expr); - throw std::runtime_error(msg); + throw std::runtime_error(std::string(msg)); #endif } -#define Expects(x) ((void)((x) || (__expect_fail("Expects failed: "#x, __FILE__, __LINE__, __func__),0))) -#define Ensures(x) ((void)((x) || (__expect_fail("Ensures failed: "#x, __FILE__, __LINE__, __func__),0))) +template +inline void __expect_failf(const char *err_prefix, const char * /*cond*/, const char *file, int line, const char *func, std::format_string fmt, Args&&... args){ + auto reason_msg = std::format(fmt, std::forward(args)...); + auto error_msg = std::format("{}:{}:{}: {}: {}", file, line, func, err_prefix, reason_msg); + __expect_emit_failure(error_msg, reason_msg); +} + +inline void __expect_failf(const char *err_prefix, const char *cond, const char *file, int line, const char *func){ + auto reason_msg = std::format("{}: {}", err_prefix, cond); + auto error_msg = std::format("{}:{}:{}: {}", file, line, func, err_prefix); + __expect_emit_failure(error_msg, reason_msg); +} + +#define Expects(cond) ((void)((cond) || (__expect_failf("Expects failed", #cond, __FILE__, __LINE__, __func__),0))) +#define Ensures(cond) ((void)((cond) || (__expect_failf("Ensures failed", #cond, __FILE__, __LINE__, __func__),0))) + +#define Expectsf(cond, fmt, ...) ((void)((cond) || (__expect_failf("Expects failed", #cond, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__),0))) +#define Ensuresf(cond, fmt, ...) ((void)((cond) || (__expect_failf("Ensures failed", #cond, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__),0))) namespace os { // parameter for noexcept specifier when bypassing noexcept for testing diff --git a/api/util/elf_binary.inc b/api/util/elf_binary.inc index 74e3967a3..559b942b4 100644 --- a/api/util/elf_binary.inc +++ b/api/util/elf_binary.inc @@ -149,7 +149,7 @@ const typename Elf_binary::Section_header& Elf_binary::section_heade template const typename Elf_binary::Span Elf_binary::section_data(const Section_header& sh) const { - return {data_.data() + sh.sh_offset, static_cast(sh.sh_size)}; + return {data_.data() + static_cast(sh.sh_offset), static_cast(sh.sh_size)}; }; template diff --git a/cmake/os.cmake b/cmake/os.cmake index bca6ddc07..851565c07 100644 --- a/cmake/os.cmake +++ b/cmake/os.cmake @@ -194,6 +194,9 @@ function(os_add_executable TARGET NAME) endif() endforeach() + find_package(fmt CONFIG REQUIRED) + target_link_libraries(${ELF_TARGET} fmt::fmt) + # TODO: if not debug strip if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(STRIP_LV ) diff --git a/deps/libfmt/default.nix b/deps/libfmt/default.nix new file mode 100644 index 000000000..2bf00f857 --- /dev/null +++ b/deps/libfmt/default.nix @@ -0,0 +1,35 @@ +# note that there is also `.fmt` +# so this entire file could just be `{ pkgs }: pkgs.fmt` +{ + pkgs, + stdenv ? pkgs.stdenv, + cmake ? pkgs.cmake +}: +let + libfmt = stdenv.mkDerivation rec { + pname = "fmt"; + version = "12.0.0"; + + src = pkgs.fetchFromGitHub { + owner = "fmtlib"; + repo = "fmt"; + rev = "12.0.0"; + hash = "sha256-AZDmIeU1HbadC+K0TIAGogvVnxt0oE9U6ocpawIgl6g="; + }; + + nativeBuildInputs = [ cmake ]; + + cmakeFlags = [ + "-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY" + "-DBUILD_SHARED_LIBS=OFF" + + "-DFMT_TEST=OFF" + "-DFMT_DOC=OFF" + "-DFMT_INSTALL=ON" + ]; + }; +in + libfmt // { + include = "${libfmt}/include"; + lib = "${libfmt}/lib"; + } diff --git a/develop.nix b/develop.nix index f0403dba3..74f59ac39 100644 --- a/develop.nix +++ b/develop.nix @@ -83,11 +83,13 @@ includeos.pkgs.mkShell.override { inherit (includeos) stdenv; } rec { jq \ --arg libcxx "${includeos.libraries.libcxx.include}" \ --arg libc "${includeos.libraries.libc}" \ - --arg localsrc "${toString ./.}" \ + --arg libfmt "${includeos.passthru.libfmt.include}" \ + --arg localsrc "${toString ./.}" \ ' map(.command |= ( . + " -isystem \($libcxx)" + " -isystem \($libc)/include" + + " -I \($libfmt)" | gsub("(?-I)(?/lib/LiveUpdate/include)"; .a + $localsrc + .b) )) ' "$CCDB" > "$tmp" && mv "$tmp" "$CCDB" diff --git a/overlay.nix b/overlay.nix index 608125f41..3b05e7e65 100644 --- a/overlay.nix +++ b/overlay.nix @@ -74,10 +74,12 @@ final: prev: { stdenv = final.stdenvIncludeOS.includeos_stdenv; # Deps - uzlib = self.callPackage ./deps/uzlib/default.nix { }; botan2 = self.callPackage ./deps/botan/default.nix { }; - s2n-tls = self.callPackage ./deps/s2n/default.nix { }; + libfmt = self.callPackage ./deps/libfmt/default.nix { }; http-parser = self.callPackage ./deps/http-parser/default.nix { }; + s2n-tls = self.callPackage ./deps/s2n/default.nix { }; + uzlib = self.callPackage ./deps/uzlib/default.nix { }; + vmbuild = self.callPackage ./vmbuild.nix { }; ccacheWrapper = prev.ccacheWrapper.override { @@ -143,6 +145,7 @@ final: prev: { ] ++ prev.lib.optionals withCcache [self.ccacheWrapper ccacheNoticeHook]; buildInputs = [ + self.libfmt self.botan2 self.http-parser prev.pkgsStatic.openssl @@ -191,6 +194,7 @@ final: prev: { inherit (self) uzlib; inherit (self) http-parser; inherit (self) botan2; + inherit (self) libfmt; #inherit (self) s2n-tls; inherit (self) cmake; inherit (self) vmbuild; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4d04b199c..00748b4ba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,10 @@ include_directories( include ) +find_package(fmt CONFIG REQUIRED) +get_target_property(libfmt_include_path fmt::fmt INTERFACE_INCLUDE_DIRECTORIES) +include_directories(${libfmt_include_path}) + #TODO move to util and check if needed / can be changed ?.. include_directories(${INCLUDEOS_ROOT}/lib/LiveUpdate/include) @@ -66,6 +70,7 @@ FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/version.h include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_library(os STATIC ${SRCS} ${OBJECTS} ${CMAKE_CURRENT_BINARY_DIR}/version.h) +target_link_libraries(os PRIVATE fmt::fmt) #TODO check if this is almost correct for platform userspace if (NOT CMAKE_TESTING_ENABLED) diff --git a/src/chainload/CMakeLists.txt b/src/chainload/CMakeLists.txt index 1a13e34d9..e79f15059 100644 --- a/src/chainload/CMakeLists.txt +++ b/src/chainload/CMakeLists.txt @@ -4,6 +4,7 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) project(chainloader C CXX) find_package(IncludeOS REQUIRED) +find_package(fmt CONFIG REQUIRED) set(ARCH i686) set(PLATFORM nano) diff --git a/src/include/kernel.hpp b/src/include/kernel.hpp index 02f129408..acdffcb44 100644 --- a/src/include/kernel.hpp +++ b/src/include/kernel.hpp @@ -26,6 +26,7 @@ namespace kernel { using namespace util; constexpr size_t default_max_mem = 2_GiB; constexpr uintptr_t page_shift = 12; + constexpr size_t kprintf_max_size = 8192; struct State { bool running = true; diff --git a/src/kernel/multiboot.cpp b/src/kernel/multiboot.cpp index f4a99bf7d..74573fdcc 100644 --- a/src/kernel/multiboot.cpp +++ b/src/kernel/multiboot.cpp @@ -21,20 +21,29 @@ #include #include #include +#include +template +static inline void _kfmt(fmt::string_view prefix, fmt::format_string fmtstr, Args&&... args) { + fmt::basic_memory_buffer buf; + fmt::format_to_n(std::back_inserter(buf), buf.capacity(), "%s", prefix); + fmt::format_to_n(std::back_inserter(buf), buf.capacity() - buf.size(), fmtstr, std::forward(args)...); + + kprintf("%.*s", (int)buf.size(), buf.data()); +} #define DEBUG_MULTIBOOT #if defined(DEBUG_MULTIBOOT) #undef debug -#define debug(X,...) kprintf(X,##__VA_ARGS__); -#define MYINFO(X,...) kprintf("" X "\n", ##__VA_ARGS__) +#define debug(fmt, ...) _kfmt("", fmt, ##__VA_ARGS__) +#undef MYINFO +#define MYINFO(fmt, ...) _kfmt("< multiboot >", fmt "\n", ##__VA_ARGS__) #undef INFO2 -#define INFO2(X,...) kprintf("\t" X "\n", ##__VA_ARGS__) +#define INFO2(fmt, ...) _kfmt("\t", fmt "\n", ##__VA_ARGS__) #else -#define debug(X,...) -#define MYINFO(X,...) INFO("Kernel", X, ##__VA_ARGS__) +#define debug(...) ((void) 0) +#define MYINFO(fmt, ,...) INFO("Kernel", X, ##__VA_ARGS__) #endif - extern uintptr_t _end; @@ -73,11 +82,11 @@ uintptr_t _multiboot_free_begin(uintptr_t boot_addr) auto* info = bootinfo(boot_addr); uintptr_t multi_end = reinterpret_cast(&_end); - debug("* Multiboot begin: 0x%lx \n", (uintptr_t)info); + debug("* Multiboot begin: {:#x}\n", (uintptr_t)info); if (info->flags & MULTIBOOT_INFO_CMDLINE and info->cmdline > multi_end) { - debug("* Multiboot cmdline @ 0x%x: %s \n", info->cmdline, reinterpret_cast(info->cmdline)); + debug("* Multiboot cmdline @ 0x{:08x}: {}\n", info->cmdline, reinterpret_cast(info->cmdline)); // We can't use a cmdline that's either insde our ELF or pre-ELF area Expects(info->cmdline > multi_end or info->cmdline < 0x100000); @@ -89,27 +98,27 @@ uintptr_t _multiboot_free_begin(uintptr_t boot_addr) } } - debug("* Multiboot end: 0x%lx \n", multi_end); + debug("* Multiboot end: {:#x}\n", multi_end); if (info->mods_count == 0) return multi_end; auto* mods_list = (multiboot_module_t*) (uintptr_t) info->mods_addr; - debug("* Module list @ %p \n",mods_list); + debug("* Module list @ {}\n", static_cast(mods_list)); for (multiboot_module_t* mod = mods_list; mod < mods_list + info->mods_count; mod ++) { - debug("\t * Module @ %#x \n", mod->mod_start); - debug("\t * Args: %s \n ", (char*) (uintptr_t) mod->cmdline); - debug("\t * End: %#x \n ", mod->mod_end); + debug("\t * Module @ {:#x}\n", mod->mod_start); + debug("\t * Args: {}\n ", (char*) (uintptr_t) mod->cmdline); + debug("\t * End: {:#x}\n", mod->mod_end); if (mod->mod_end > multi_end) multi_end = mod->mod_end; } - debug("* Multiboot end: 0x%lx \n", multi_end); + debug("* Multiboot end: {} \n", multi_end); return multi_end; } @@ -117,7 +126,7 @@ void kernel::multiboot(uint32_t boot_addr) { MYINFO("Booted with multiboot"); auto* info = ::bootinfo(boot_addr); - INFO2("* Boot flags: %#x", info->flags); + INFO2("* Boot flags: {:#x}", info->flags); if (info->flags & MULTIBOOT_INFO_MEMORY) { uint32_t mem_low_start = 0; @@ -127,11 +136,9 @@ void kernel::multiboot(uint32_t boot_addr) uint32_t mem_high_end = mem_high_start + (info->mem_upper * 1024) - 1; uint32_t mem_high_kb = info->mem_upper; - INFO2("* Valid memory (%i Kib):", mem_low_kb + mem_high_kb); - INFO2(" 0x%08x - 0x%08x (%i Kib)", - mem_low_start, mem_low_end, mem_low_kb); - INFO2(" 0x%08x - 0x%08x (%i Kib)", - mem_high_start, mem_high_end, mem_high_kb); + INFO2("* Valid memory (%i KiB):", mem_low_kb + mem_high_kb); + INFO2(" 0x{:08x} - 0x{:08x} ({} KiB)", mem_low_start, mem_low_end, mem_low_kb); + INFO2(" 0x{:08x} - 0x{:08x} ({} KiB)", mem_high_start, mem_high_end, mem_high_kb); INFO2(""); } else { @@ -140,14 +147,14 @@ void kernel::multiboot(uint32_t boot_addr) if (info->flags & MULTIBOOT_INFO_CMDLINE) { const auto* cmdline = (const char*) (uintptr_t) info->cmdline; - INFO2("* Booted with parameters @ %p: %s", cmdline, cmdline); + INFO2("* Booted with parameters @ {}: {}", (const void*)(uintptr_t)info->cmdline, cmdline); kernel::state().cmdline = std::pmr::string(cmdline).data(); } if (info->flags & MULTIBOOT_INFO_MEM_MAP) { - INFO2("* Multiboot provided memory map (%zu entries @ %p)", + INFO2("* Multiboot provided memory map ({} entries @ {})", info->mmap_length / sizeof(multiboot_memory_map_t), - (void*) (uintptr_t) info->mmap_addr); + (const void*)(uintptr_t)info->mmap_addr); std::span mmap { reinterpret_cast(info->mmap_addr), static_cast(info->mmap_length / sizeof(multiboot_memory_map_t)) @@ -158,8 +165,7 @@ void kernel::multiboot(uint32_t boot_addr) const char* str_type = map.type & MULTIBOOT_MEMORY_AVAILABLE ? "FREE" : "RESERVED"; const uintptr_t addr = map.addr; const uintptr_t size = map.len; - INFO2(" 0x%010zx - 0x%010zx %s (%zu Kb.)", - addr, addr + size - 1, str_type, size / 1024 ); + INFO2(" {:#x} - {:#x} {} ({} KiB)", addr, addr + size - 1, str_type, size / 1024); if (not (map.type & MULTIBOOT_MEMORY_AVAILABLE)) { @@ -184,9 +190,9 @@ void kernel::multiboot(uint32_t boot_addr) auto mods = os::modules(); if (not mods.empty()) { - MYINFO("OS loaded with %zu modules", mods.size()); + MYINFO("OS loaded with {} modules", mods.size()); for (auto mod : mods) { - INFO2("* %s @ 0x%x - 0x%x, size: %ib", + INFO2("* {} @ 0x{:08x} - 0x{:08x}, size: {} B", reinterpret_cast(mod.params), mod.mod_start, mod.mod_end, mod.mod_end - mod.mod_start); } diff --git a/src/kernel/profile.cpp b/src/kernel/profile.cpp index 3ca553ddb..3c6f25f45 100644 --- a/src/kernel/profile.cpp +++ b/src/kernel/profile.cpp @@ -203,24 +203,60 @@ void StackSampler::set_mask(bool mask) get().discard = mask; } -std::string HeapDiag::to_string() -{ - static intptr_t last = 0; + +inline std::string to_human_size(std::uint64_t bytes) { + constexpr std::string_view size_suffixes[] = { + "B", "KiB", "MiB", "GiB", "TiB", "PiB" + }; + double value = static_cast(bytes); + std::size_t exponent = 0; + + while (value >= 1024.0 && exponent + 1 < std::size(size_suffixes)) { + value /= 1024.0; + exponent++; + } + + if (exponent == 0) + return std::format("{} {}", static_cast(value), size_suffixes[exponent]); + else + return std::format("{:.2f} {}", value, size_suffixes[exponent]); +} + +inline std::string with_thousands_sep(uint64_t value, char sep = '_', char every = 3) { + std::string s = std::to_string(value); + for (int i = s.size() - every; i > 0; i -= every) + s.insert(i, 1, sep); + return s; +} + +std::string HeapDiag::to_string() { + // TODO: check if heap should be 64 bit instead + static intptr_t last_size = 0; + // show information on heap status, to discover leaks etc. - auto heap_begin = kernel::heap_begin(); - auto heap_end = kernel::heap_end(); - auto heap_usage = kernel::heap_usage(); - intptr_t heap_size = heap_end - heap_begin; - last = heap_size - last; - - char buffer[256]; - int len = snprintf(buffer, sizeof(buffer), - "Heap begin %#lx size %lu Kb\n" - "Heap end %#lx diff %lu (%ld Kb)\n" - "Heap usage %lu kB\n", - heap_begin, heap_size / 1024, - heap_end, last, last / 1024, - heap_usage / 1024); - last = (int32_t) heap_size; - return std::string(buffer, len); + const uintptr_t heap_begin = kernel::heap_begin(); + const uintptr_t heap_end = kernel::heap_end(); + const size_t heap_usage = kernel::heap_usage(); + + const size_t heap_size = heap_end - heap_begin; + const size_t heap_growth = heap_size - last_size; + + auto buffer = std::format( + "Logged last size {} ({} bytes)\n" + "Reported heap begin {:#010x}\n" // 32-bit system = 8 hex chars ("0x" += 2) + "Reported heap end {:#010x}\n" + "(end-begin) usage {} ({} bytes)\n" + "Reported usage {} ({} bytes)\n" + "Δ(end-begin) {} ({} bytes)\n" + , + to_human_size(last_size), with_thousands_sep(last_size), + heap_begin, + heap_end, + to_human_size(heap_size), with_thousands_sep(heap_size), + to_human_size(heap_usage), with_thousands_sep(heap_usage), + to_human_size(heap_growth), with_thousands_sep(heap_growth) + ); + + last_size = (int32_t) heap_size; + return buffer; } diff --git a/src/musl/mmap.cpp b/src/musl/mmap.cpp index 1f452dde0..691681691 100644 --- a/src/musl/mmap.cpp +++ b/src/musl/mmap.cpp @@ -60,6 +60,11 @@ static void* sys_mmap(void * addr, size_t length, int /*prot*/, int flags, // TODO: Implement minimal functionality to be POSIX compliant // https://pubs.opengroup.org/onlinepubs/009695399/functions/mmap.html + if (length <= 0) { + Expectsf(false, "Must always allocate at least 1 byte. Got {}", length); + errno = EINVAL; + return MAP_FAILED; + } if (fd > -1) { // None of our file systems support memory mapping at the moment diff --git a/src/net/packet_debug.cpp b/src/net/packet_debug.cpp index 51d5e4b10..20e85e835 100644 --- a/src/net/packet_debug.cpp +++ b/src/net/packet_debug.cpp @@ -39,7 +39,7 @@ namespace net { fprintf(stderr, "Buffer: Begin: %p End: %p Size: %i\n", pkt->buf(), pkt->buffer_end(), pkt->bufsize()); const size_t offset = pkt->layer_begin() - layer_begin; - fprintf(stderr, "Layer: Recorded: %p Current: %p (%lub offset)\n", + fprintf(stderr, "Layer: Recorded: %p Current: %p (%zub offset)\n", layer_begin, pkt->layer_begin(), offset); fprintf(stderr, "Size: %i ", pkt->size()); fprintf(stderr, "Capacity: %i ", pkt->capacity()); diff --git a/src/platform/x86_pc/apic_revenant.cpp b/src/platform/x86_pc/apic_revenant.cpp index f3354ca71..bca2c6795 100644 --- a/src/platform/x86_pc/apic_revenant.cpp +++ b/src/platform/x86_pc/apic_revenant.cpp @@ -17,6 +17,7 @@ namespace x86 { extern "C" void* get_cpu_esp(); extern "C" void lapic_exception_handler(); +#undef INFO // api/info uses kprint #define INFO(FROM, TEXT, ...) printf("%13s ] " TEXT "\n", "[ " FROM, ##__VA_ARGS__) using namespace x86; diff --git a/src/platform/x86_pc/idt.cpp b/src/platform/x86_pc/idt.cpp index 9344199ea..3d07f969a 100644 --- a/src/platform/x86_pc/idt.cpp +++ b/src/platform/x86_pc/idt.cpp @@ -276,7 +276,7 @@ void __page_fault(uintptr_t* regs, uint32_t code) { if (not(code & 1)) reason = "Page not present"; - fprintf(stderr,"%s, trying to access 0x%lx\n", reason, addr); + fprintf(stderr,"%s, trying to access %p\n", reason, (void*)addr); if (code & 2) fprintf(stderr,"Page write failed.\n"); diff --git a/src/platform/x86_pc/serial1.cpp b/src/platform/x86_pc/serial1.cpp index 99125be2e..e18ad0b41 100644 --- a/src/platform/x86_pc/serial1.cpp +++ b/src/platform/x86_pc/serial1.cpp @@ -1,3 +1,4 @@ +#include "kernel.hpp" #include #include static const uint16_t port = 0x3F8; // Serial 1 @@ -44,7 +45,7 @@ void kprint(const char* c){ extern "C" void kprintf(const char* format, ...) { - char buf[8192]; + char buf[kernel::kprintf_max_size]; va_list aptr; va_start(aptr, format); vsnprintf(buf, sizeof(buf), format, aptr); diff --git a/test/kernel/integration/rng/service.cpp b/test/kernel/integration/rng/service.cpp index 4791cabfb..f997efbd6 100644 --- a/test/kernel/integration/rng/service.cpp +++ b/test/kernel/integration/rng/service.cpp @@ -45,7 +45,7 @@ void Service::start() memset(a, 0, BUFLEN); memset(b, 0, BUFLEN); - CHECKSERT(read(rand_fd, a, sizeof(a)) == sizeof(a), "read returns the correct length (%u)", BUFLEN); + CHECKSERT(read(rand_fd, a, sizeof(a)) == sizeof(a), "read returns the correct length (%zu)", BUFLEN); read(rand_fd, b, sizeof(b)); CHECKSERT(memcmp(a, b, BUFLEN) != 0, "reading returns new data"); diff --git a/test/net/integration/bufstore/service.cpp b/test/net/integration/bufstore/service.cpp index 1db42fb59..2973ab141 100644 --- a/test/net/integration/bufstore/service.cpp +++ b/test/net/integration/bufstore/service.cpp @@ -70,7 +70,7 @@ void Service::start(const std::string&) "Bufcount is now %u", BUFFER_CNT - 1); // Chain - for (int i = 0; i < TOTAL_BUFFERS-1; i++){ + for (size_t i = 0; i < TOTAL_BUFFERS-1; i++){ auto chained_packet = create_packet(bufstore); packet->chain(std::move(chained_packet)); } @@ -87,7 +87,7 @@ void Service::start(const std::string&) tail = 0; packet = 0; CHECK(bufstore.available() == TOTAL_BUFFERS, - "Bufcount is now %u / %u", bufstore.available(), TOTAL_BUFFERS); + "Bufcount is now %zu / %u", bufstore.available(), TOTAL_BUFFERS); //assert(bufstore.available() == TOTAL_BUFFERS); INFO("Tests","SUCCESS"); } diff --git a/test/net/unit/conntrack_test.cpp b/test/net/unit/conntrack_test.cpp index 2814720ff..b35398ec8 100644 --- a/test/net/unit/conntrack_test.cpp +++ b/test/net/unit/conntrack_test.cpp @@ -181,7 +181,7 @@ CASE("Testing Conntrack serialization") // This one aint gonna be serialized auto* with_close_handler = ct->simple_track_in(rquad, Protocol::ICMPv4); - with_close_handler->on_close = [](auto* ent) { ent->state; }; + with_close_handler->on_close = [](auto* ent) { (void)ent->state; }; EXPECT(ct->number_of_entries() == 6); diff --git a/unittests.nix b/unittests.nix index 7b91847e3..589d4502c 100644 --- a/unittests.nix +++ b/unittests.nix @@ -48,9 +48,11 @@ stdenv.mkDerivation rec { lest = pkgs.callPackage ./deps/lest {}; uzlib = pkgs.callPackage ./deps/uzlib {}; + libfmt = pkgs.callPackage ./deps/libfmt { stdenv = stdenv; }; passthru = { inherit lest; + inherit libfmt; }; nativeBuildInputs = [ @@ -65,5 +67,6 @@ stdenv.mkDerivation rec { pkgs.openssl lest uzlib + libfmt ]; } diff --git a/vmbuild/vmbuild.cpp b/vmbuild/vmbuild.cpp index d173ad7c9..e3dd2d7ee 100644 --- a/vmbuild/vmbuild.cpp +++ b/vmbuild/vmbuild.cpp @@ -36,12 +36,30 @@ #define SECT_SIZE_ERR 666 #define DISK_SIZE_ERR 999 -bool verb = false; +#include +static bool verbose = false; + +template +inline void infof(const char* from, std::format_string fmt, Args&&... args) { + if (!verbose) return; + auto msg = std::format(fmt, std::forward(args)...); + std::fprintf(stderr, "[ %13s ] %s\n", from, msg.c_str()); +} +template +inline void warnf(const char* from, std::format_string fmt, Args&&... args) { + auto msg = std::format(fmt, std::forward(args)...); + std::fprintf(stderr, "[ %13s ] Warning: %s\n", from, msg.c_str()); +} +template +[[noreturn]] inline void errorf(const char* from, std::format_string fmt, Args&&... args) { + auto msg = std::format(fmt, std::forward(args)...); + std::fprintf(stderr, "[ %13s ] Error: %s\n", from, msg.c_str()); + std::terminate(); +} -#define INFO_(FROM, TEXT, ...) if (verb) fprintf(stderr, "%13s ] " TEXT "\n", "[ " FROM, ##__VA_ARGS__) -#define INFO(X,...) INFO_("Vmbuild", X, ##__VA_ARGS__) -#define WARN(X,...) fprintf(stderr, "[ vmbuild ] Warning: " X "\n", ##__VA_ARGS__) -#define ERROR(X,...) fprintf(stderr, "[ vmbuild ] Error: " X "\n", ##__VA_ARGS__); std::terminate() +#define INFO(FMT, ...) infof("vmbuild", FMT, ##__VA_ARGS__) +#define WARN(FMT, ...) warnf("vmbuild", FMT, ##__VA_ARGS__) +#define ERROR(FMT, ...) errorf("vmbuild", FMT, ##__VA_ARGS__) // Special variables inside the bootloader @@ -95,26 +113,26 @@ int main(int argc, char** argv) // Set verbose from environment const char* env_verb = getenv("VERBOSE"); if (env_verb && strlen(env_verb) > 0) - verb = true; + verbose = true; const std::string bootloader_path = get_bootloader_path(argc, argv); if (argc > 2) const std::string bootloader_path {argv[2]}; - INFO("Using bootloader %s" , bootloader_path.c_str()); + INFO("Using bootloader {}", bootloader_path); const std::string elf_binary_path {argv[1]}; const std::string img_name {elf_binary_path.substr(elf_binary_path.find_last_of("/") + 1, std::string::npos) + ".img"}; - INFO("Creating image '%s'" , img_name.c_str()); + INFO("Creating image '{}'", img_name); if (argc > 3) { if (std::string{argv[3]} == "-test") { test = true; - verb = true; + verbose = true; } else if (std::string{argv[3]} == "-v"){ - verb = true; + verbose = true; } } @@ -123,39 +141,39 @@ int main(int argc, char** argv) // Validate boot loader if (stat(bootloader_path.c_str(), &stat_boot) == -1) { - INFO("Could not open %s, exiting\n" , bootloader_path.c_str()); + INFO("Could not open {}, exiting", bootloader_path); return errno; } if (stat_boot.st_size != SECT_SIZE) { - INFO("Boot sector not exactly one sector in size (%ld bytes, expected %i)", + INFO("Boot sector not exactly one sector in size ({} bytes, expected {})", stat_boot.st_size, SECT_SIZE); return SECT_SIZE_ERR; } - INFO("Size of bootloader: %ld\t" , stat_boot.st_size); + INFO("Size of bootloader: {}", stat_boot.st_size); // Validate service binary location if (stat(elf_binary_path.c_str(), &stat_binary) == -1) { - ERROR("vmbuild: Could not open '%s'\n" , elf_binary_path.c_str()); + ERROR("vmbuild: Could not open '{}'", elf_binary_path); return errno; } intmax_t binary_sectors = stat_binary.st_size / SECT_SIZE; if (stat_binary.st_size & (SECT_SIZE-1)) binary_sectors += 1; - INFO("Size of service: \t%ld bytes" , stat_binary.st_size); + INFO("Size of service: {} bytes", stat_binary.st_size); const decltype(binary_sectors) img_size_sect {1 + binary_sectors}; const decltype(binary_sectors) img_size_bytes {img_size_sect * SECT_SIZE}; assert((img_size_bytes & (SECT_SIZE-1)) == 0); - INFO("Total disk size: \t%ld bytes, => %ld sectors", + INFO("Total disk size: {} bytes, => {} sectors", img_size_bytes, img_size_sect); const auto disk_size = img_size_bytes; - INFO("Creating disk of size %ld sectors / %ld bytes" , + INFO("Creating disk of size {} sectors / {} bytes" , (disk_size / SECT_SIZE), disk_size); std::vector disk (disk_size); @@ -165,14 +183,14 @@ int main(int argc, char** argv) std::ifstream file_boot {bootloader_path}; //< Load the boot loader into memory auto read_bytes = file_boot.read(disk_head, stat_boot.st_size).gcount(); - INFO("Read %ld bytes from boot image", read_bytes); + INFO("Read {} bytes from boot image", read_bytes); std::ifstream file_binary {elf_binary_path}; //< Load the service into memory auto* binary_imgloc = disk_head + SECT_SIZE; //< Location of service code within the image read_bytes = file_binary.read(binary_imgloc, stat_binary.st_size).gcount(); - INFO("Read %ld bytes from service image" , read_bytes); + INFO("Read {} bytes from service image", read_bytes); // only accept ELF binaries if (not (binary_imgloc[EI_MAG0] == ELFMAG0 @@ -193,15 +211,15 @@ int main(int argc, char** argv) // 32-bit ELF if (binary_imgloc[EI_CLASS] == ELFCLASS32) { - Elf_binary binary ({binary_imgloc, stat_binary.st_size}); + Elf_binary binary ({binary_imgloc, static_cast(stat_binary.st_size)}); binary.validate(); srv_entry = binary.entry(); - INFO("Found 32-bit ELF with entry at 0x%x", srv_entry); + INFO("Found 32-bit ELF with entry at {:#010x}", srv_entry); auto loadable = binary.loadable_segments(); if (loadable.size() > 1) { - WARN("found %zu loadable segments. Loading as one.",loadable.size()); + WARN("found {} loadable segments. Loading as one.", loadable.size()); } srv_load_addr = loadable[0]->p_paddr; binary_load_offs = loadable[0]->p_offset; @@ -214,11 +232,11 @@ int main(int argc, char** argv) // 64-bit ELF else if (binary_imgloc[EI_CLASS] == ELFCLASS64) { - Elf_binary binary ({binary_imgloc, stat_binary.st_size}); + Elf_binary binary ({binary_imgloc, static_cast(stat_binary.st_size)}); binary.validate(); srv_entry = binary.entry(); - INFO("Found 64-bit ELF with entry at 0x%x", srv_entry); + INFO("Found 64-bit ELF with entry at {:#010x}", srv_entry); auto loadable = binary.loadable_segments(); // Expects(loadable.size() == 1); @@ -238,25 +256,25 @@ int main(int argc, char** argv) INFO("Verifying multiboot header:"); - INFO("Magic value: 0x%x" , multiboot_hdr->magic); + INFO("Magic value: {:#010x}", multiboot_hdr->magic); if (multiboot_hdr->magic != MULTIBOOT_HEADER_MAGIC) { - ERROR("Multiboot magic mismatch: 0x%08x vs %#x", + ERROR("Multiboot magic mismatch: {:#010x} vs {:#x}", multiboot_hdr->magic, MULTIBOOT_HEADER_MAGIC); } - - INFO("Flags: 0x%x" , multiboot_hdr->flags); - INFO("Checksum: 0x%x" , multiboot_hdr->checksum); - INFO("Checksum computed: 0x%x", multiboot_hdr->checksum + multiboot_hdr->flags + multiboot_hdr->magic); + INFO("Flags: {:#010x}", multiboot_hdr->flags); + INFO("Checksum: {:#010x}", multiboot_hdr->checksum); + INFO("Checksum computed: {:#010x}", + multiboot_hdr->checksum + multiboot_hdr->flags + multiboot_hdr->magic); // Verify multiboot header checksum assert(multiboot_hdr->checksum + multiboot_hdr->flags + multiboot_hdr->magic == 0); - INFO("Header addr: 0x%x" , multiboot_hdr->header_addr); - INFO("Load start: 0x%x" , multiboot_hdr->load_addr); - INFO("Load end: 0x%x" , multiboot_hdr->load_end_addr); - INFO("BSS end: 0x%x" , multiboot_hdr->bss_end_addr); - INFO("Entry: 0x%x" , multiboot_hdr->entry_addr); + INFO("Header addr: {:#010x}", multiboot_hdr->header_addr); + INFO("Load start: {:#010x}", multiboot_hdr->load_addr); + INFO("Load end: {:#010x}", multiboot_hdr->load_end_addr); + INFO("BSS end: {:#010x}", multiboot_hdr->bss_end_addr); + INFO("Entry: {:#010x}", multiboot_hdr->entry_addr); assert(multiboot_hdr->entry_addr == srv_entry); @@ -272,9 +290,9 @@ int main(int argc, char** argv) boot->entry = srv_entry; boot->load_addr = srv_load_addr; - INFO("srv_size: %i", srv_size); - INFO("srv_entry: 0x%x", srv_entry); - INFO("srv_load: 0x%x", srv_load_addr); + INFO("srv_size: {}", srv_size); + INFO("srv_entry: {:#010x}", srv_entry); + INFO("srv_load: {:#010x}", srv_load_addr); if (test) { INFO("\nTEST overwriting service with testdata"); @@ -287,8 +305,8 @@ int main(int argc, char** argv) auto* image = fopen(img_name.c_str(), "w"); auto wrote = fwrite(disk_head, 1, disk_size, image); - INFO("Wrote %ld bytes => %ld sectors to '%s'", - wrote, (wrote / SECT_SIZE), img_name.c_str()); + INFO("Wrote {} bytes => {} sectors to '{}'", + wrote, (wrote / SECT_SIZE), img_name); fclose(image); }