diff --git a/kernel/src/Hal/IDT.cpp b/kernel/src/Hal/IDT.cpp index 1b69938..5fb077d 100644 --- a/kernel/src/Hal/IDT.cpp +++ b/kernel/src/Hal/IDT.cpp @@ -71,6 +71,13 @@ namespace Hal { return frame->CS; } + static System::PanicFrame* GetExceptionRegs(uint8_t vector, System::PanicFrame* frame) { + if (ExceptionHasErrorCode(vector)) { + return (System::PanicFrame*)((uint8_t*)frame + sizeof(uint64_t)); + } + return frame; + } + template __attribute__((interrupt)) void ExceptionHandler(System::PanicFrame* frame) { @@ -85,6 +92,7 @@ namespace Hal { // instead of panicking the entire system. if (fromUser && Sched::GetCurrentPid() >= 0) { auto* proc = Sched::GetCurrentProcessPtr(); + auto* regs = GetExceptionRegs(i, frame); Kt::KernelLogStream(Kt::ERROR, "Exception") << ExceptionStrings[i] << " in process \"" << proc->name << "\" (pid " << proc->pid @@ -99,11 +107,11 @@ namespace Hal { rep.exceptionVector = i; for (int j = 0; j < 32 && ExceptionStrings[i][j]; j++) rep.exceptionName[j] = ExceptionStrings[i][j]; rep.exceptionName[31] = '\0'; - rep.instructionPointer = frame->IP; - rep.codeSegment = frame->CS; - rep.flags = frame->Flags; - rep.stackPointer = frame->SP; - rep.stackSegment = frame->SS; + rep.instructionPointer = regs->IP; + rep.codeSegment = regs->CS; + rep.flags = regs->Flags; + rep.stackPointer = regs->SP; + rep.stackSegment = regs->SS; if (i == 0x0E) { // Page fault: read CR2 for faulting address @@ -215,4 +223,4 @@ namespace Hal { void IDTReload() { LoadIDT(IDTR); } -}; \ No newline at end of file +}; diff --git a/kernel/src/Sched/ElfLoader.cpp b/kernel/src/Sched/ElfLoader.cpp index 7c5d00f..7f6506d 100644 --- a/kernel/src/Sched/ElfLoader.cpp +++ b/kernel/src/Sched/ElfLoader.cpp @@ -268,10 +268,11 @@ namespace Sched { uint64_t copyEnd = (pageEnd < targetSegFileEnd) ? pageEnd : targetSegFileEnd; if (copyStart < copyEnd) { - // Source: file data at (copyStart - targetSegStart) offset from p_offset + // Source stays segment-relative, but the destination must be page-relative. + // Using a segment-relative destination offset leaves page 2+ zero-filled and + // writes past the newly allocated page in the kernel mapping. uint64_t srcOffset = phdr->p_offset + (copyStart - targetSegStart); - // Dest: page at (copyStart - targetSegStart) offset, then adjusted for this page - uint64_t pageDataOffset = copyStart - targetSegStart; + uint64_t pageDataOffset = copyStart - pageStart; uint64_t copySize = copyEnd - copyStart; uint8_t* dst = (uint8_t*)Memory::HHDM(physAddr) + pageDataOffset; diff --git a/programs/GNUmakefile b/programs/GNUmakefile index 1502823..387e69b 100644 --- a/programs/GNUmakefile +++ b/programs/GNUmakefile @@ -281,8 +281,8 @@ dialogs: bearssl libc tls crashpad: libc $(MAKE) -C src/crashpad -# Build test_dl (dynamic loading test app, depends on libloader). -test_dl: libloader libs +# Build test_dl (dynamic loading test app, depends on libloader and shared libs). +test_dl: libloader libs libhello $(MAKE) -C src/test_dl # Install app bundles (manifests, icons, data files) into bin/apps//. diff --git a/programs/libs/libhello/Makefile b/programs/libs/libhello/Makefile index 5adebf1..5eada70 100644 --- a/programs/libs/libhello/Makefile +++ b/programs/libs/libhello/Makefile @@ -11,6 +11,8 @@ NM := $(TOOLCHAIN_PREFIX)nm STRIP := $(TOOLCHAIN_PREFIX)strip # Compiler flags: freestanding, no stdlib +# Build as PIE so library-internal data references remain valid after the +# kernel maps the image into a per-process library slot. override CXXFLAGS := \ -std=gnu++20 \ -g -O2 -pipe \ @@ -20,7 +22,7 @@ override CXXFLAGS := \ -ffreestanding \ -fno-stack-protector \ -fno-stack-check \ - -fno-PIC \ + -fPIE \ -fno-rtti \ -fno-exceptions \ -ffunction-sections \ diff --git a/programs/libs/libhello/src/libhello.cpp b/programs/libs/libhello/src/libhello.cpp index 7e88c78..f8eceb5 100644 --- a/programs/libs/libhello/src/libhello.cpp +++ b/programs/libs/libhello/src/libhello.cpp @@ -8,18 +8,47 @@ #include #include -// Exported demo function - creates a window and renders until closed +// Heap allocation test - allocates, writes, reads, frees +// Returns 0 on success, -1 on failure +extern "C" int hello_malloc_test() { + // Test 1: Allocate 256 bytes + void* buf = montauk::malloc(256); + if (!buf) { + montauk::print(" [libhello] malloc(256) failed\n"); + return -1; + } + + // Test 2: Write a pattern and verify it + uint8_t* bytes = (uint8_t*)buf; + for (int i = 0; i < 256; i++) { + bytes[i] = (uint8_t)(i & 0xFF); + } + for (int i = 0; i < 256; i++) { + if (bytes[i] != (uint8_t)(i & 0xFF)) { + montauk::print(" [libhello] read verification failed\n"); + montauk::mfree(buf); + return -1; + } + } + + montauk::mfree(buf); + return 0; +} + extern "C" int hello_run() { // Create window + static constexpr int kInitialWidth = 320; + static constexpr int kInitialHeight = 200; + static constexpr uint32_t kBackgroundColor = 0xFFFFFFFF; Montauk::WinCreateResult wres; - if (montauk::win_create("libhello Demo", 320, 200, &wres) < 0 || wres.id < 0) { + if (montauk::win_create("libhello Demo", kInitialWidth, kInitialHeight, &wres) < 0 || wres.id < 0) { return -1; } int winId = wres.id; uint32_t* pixels = (uint32_t*)(uintptr_t)wres.pixelVa; - int width = 200; - int height = 320; + int width = kInitialWidth; + int height = kInitialHeight; gui::TrueTypeFont* font = (gui::TrueTypeFont*)montauk::malloc(sizeof(gui::TrueTypeFont)); if (!font) { @@ -36,16 +65,15 @@ extern "C" int hello_run() { // Simple render - fill with a color pattern for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - // Dark blue background - pixels[y * width + x] = 0xFF1a1a2e; + pixels[y * width + x] = kBackgroundColor; } } // Render text using TrueType gui::Color text_color; - text_color.r = 0xF5; - text_color.g = 0xF5; - text_color.b = 0xF5; + text_color.r = 0x11; + text_color.g = 0x11; + text_color.b = 0x11; text_color.a = 255; font->draw_to_buffer(pixels, width, height, 20, 20, "Hello from libhello!", text_color, 16); @@ -76,7 +104,7 @@ extern "C" int hello_run() { // Re-render on resize for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - pixels[y * width + x] = 0xFF1a1a2e; + pixels[y * width + x] = kBackgroundColor; } } font->draw_to_buffer(pixels, width, height, 20, 20, "Hello from libhello!", text_color, 16); diff --git a/programs/libs/libhello/src/libhello.o b/programs/libs/libhello/src/libhello.o index 74abc1c..c5158f9 100644 Binary files a/programs/libs/libhello/src/libhello.o and b/programs/libs/libhello/src/libhello.o differ diff --git a/programs/libs/libhello/src/stb_truetype_impl.o b/programs/libs/libhello/src/stb_truetype_impl.o index 292d609..4d66d60 100644 Binary files a/programs/libs/libhello/src/stb_truetype_impl.o and b/programs/libs/libhello/src/stb_truetype_impl.o differ diff --git a/programs/libs/libmath/Makefile b/programs/libs/libmath/Makefile index 2400559..42c5160 100644 --- a/programs/libs/libmath/Makefile +++ b/programs/libs/libmath/Makefile @@ -11,6 +11,8 @@ NM := $(TOOLCHAIN_PREFIX)nm STRIP := $(TOOLCHAIN_PREFIX)strip # Compiler flags: freestanding, no stdlib +# Build as PIE so library code remains valid when loaded into a slot-specific +# base address by the kernel loader. override CXXFLAGS := \ -std=gnu++20 \ -g -O2 -pipe \ @@ -20,7 +22,7 @@ override CXXFLAGS := \ -ffreestanding \ -fno-stack-protector \ -fno-stack-check \ - -fno-PIC \ + -fPIE \ -fno-rtti \ -fno-exceptions \ -ffunction-sections \ @@ -55,7 +57,7 @@ LIBSRC := src/libmath.cpp all: $(OUTDIR)/$(LIBNAME).lib $(OUTDIR)/$(LIBNAME).lib.sym -$(OUTDIR)/$(LIBNAME).lib: $(LIBSRC) +$(OUTDIR)/$(LIBNAME).lib: $(LIBSRC) Makefile @mkdir -p $(OUTDIR) $(CXX) $(CXXFLAGS) -c $(LIBSRC) -o src/libmath.o $(CXX) $(CXXFLAGS) $(LDFLAGS) src/libmath.o -o $@ diff --git a/programs/libs/libmath/src/libmath.o b/programs/libs/libmath/src/libmath.o index 011df75..ab3ae21 100644 Binary files a/programs/libs/libmath/src/libmath.o and b/programs/libs/libmath/src/libmath.o differ diff --git a/programs/src/test_dl/main.cpp b/programs/src/test_dl/main.cpp index c7b18d0..86b9a08 100644 --- a/programs/src/test_dl/main.cpp +++ b/programs/src/test_dl/main.cpp @@ -100,7 +100,26 @@ extern "C" void _start() { // Debug: print hello_run address montauk::print(" DEBUG: hello_run @ "); print_hex((uint64_t)hello_run); - montauk::print("\n"); + montauk::print("\n\n"); + + // Test heap allocations in the shared library + montauk::print("Testing heap allocations in libhello...\n"); + typedef int (*malloc_test_t)(void); + malloc_test_t malloc_test = (malloc_test_t)libloader::dlsym(hellolib, "hello_malloc_test"); + if (!malloc_test) { + montauk::print("ERROR: Failed to resolve hello_malloc_test\n"); + libloader::dlclose(hellolib); + montauk::exit(1); + } + montauk::print(" hello_malloc_test: OK\n"); + + int malloc_result = malloc_test(); + if (malloc_result != 0) { + montauk::print("ERROR: heap allocation test in libhello failed\n"); + libloader::dlclose(hellolib); + montauk::exit(1); + } + montauk::print(" heap allocation test: PASSED\n\n"); // Run the GUI demo (this creates a window and event loop) montauk::print("Running GUI demo...\n");