wip: extend shared library support, window demo

This commit is contained in:
2026-04-05 21:38:05 +02:00
parent 01c242d4de
commit 6f0707bc80
14 changed files with 268 additions and 53 deletions
+2
View File
@@ -417,6 +417,8 @@ namespace Montauk {
return Sys_UnloadLib(frame->arg1);
case SYS_DLSYM:
return (int64_t)Sys_DLSym(frame->arg1, frame->arg2);
case SYS_GETLIBBASE:
return (int64_t)Sys_GetLibBase(frame->arg1);
default:
return -1;
}
+1
View File
@@ -210,6 +210,7 @@ namespace Montauk {
static constexpr uint64_t SYS_LOAD_LIB = 114;
static constexpr uint64_t SYS_UNLOAD_LIB = 115;
static constexpr uint64_t SYS_DLSYM = 116;
static constexpr uint64_t SYS_GETLIBBASE = 117;
static constexpr uint32_t IPC_SIGNAL_READABLE = 1u << 0;
static constexpr uint32_t IPC_SIGNAL_WRITABLE = 1u << 1;
+3 -3
View File
@@ -270,11 +270,11 @@ namespace Sched {
if (copyStart < copyEnd) {
// Source: file data at (copyStart - targetSegStart) offset from p_offset
uint64_t srcOffset = phdr->p_offset + (copyStart - targetSegStart);
// Dest: page at (copyStart - pageStart) offset
uint64_t dstOffset = copyStart - pageStart;
// Dest: page at (copyStart - targetSegStart) offset, then adjusted for this page
uint64_t pageDataOffset = copyStart - targetSegStart;
uint64_t copySize = copyEnd - copyStart;
uint8_t* dst = (uint8_t*)Memory::HHDM(physAddr) + dstOffset;
uint8_t* dst = (uint8_t*)Memory::HHDM(physAddr) + pageDataOffset;
uint8_t* src = fileData + srcOffset;
memcpy(dst, src, copySize);
}
+8 -3
View File
@@ -59,7 +59,7 @@ BINDIR := bin
PROGRAMS := $(notdir $(wildcard src/*))
# Programs with custom Makefiles (built separately).
CUSTOM_BUILDS := doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet wordprocessor pdfviewer disks devexplorer installer volume music video bluetooth terminal klog procmgr calculator desktop login shell rpgdemo paint tcc lua screenshot texteditor mandelbrot printers printd printctl dialogs test_dl libloader
CUSTOM_BUILDS := doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet wordprocessor pdfviewer disks devexplorer installer volume music video bluetooth terminal klog procmgr calculator desktop login shell rpgdemo paint tcc lua screenshot texteditor mandelbrot printers printd printctl dialogs test_dl libloader libhello
SYSTEM_PROGRAMS := $(filter-out $(CUSTOM_BUILDS),$(PROGRAMS))
# Build targets: system programs go to bin/os/, apps go to bin/apps/<name>/.
@@ -81,9 +81,9 @@ CA_CERTS := $(BINDIR)/etc/ca-certificates.crt
# Common shared assets (wallpapers, etc.)
COMMONKEEP := $(BINDIR)/common/.keep
.PHONY: all clean doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet wordprocessor pdfviewer disks devexplorer installer volume music video bluetooth terminal klog procmgr calculator login desktop shell rpgdemo paint tcc lua screenshot texteditor mandelbrot printers printd printctl dialogs icons fonts bearssl libc tls libjpeg libjpegwrite install-apps libloader libs test_dl
.PHONY: all clean doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet wordprocessor pdfviewer disks devexplorer installer volume music video bluetooth terminal klog procmgr calculator login desktop shell rpgdemo paint tcc lua screenshot texteditor mandelbrot printers printd printctl dialogs icons fonts bearssl libc tls libjpeg libjpegwrite install-apps libloader libs libhello test_dl
all: bearssl libc libjpeg libjpegwrite tls libloader libs $(TARGETS) fetch wiki wikipedia weather imageviewer fontpreview spreadsheet wordprocessor pdfviewer disks devexplorer installer volume music video bluetooth terminal klog procmgr calculator doom rpgdemo paint tcc lua screenshot texteditor mandelbrot printers printd printctl dialogs login desktop shell icons fonts install-apps test_dl $(MANDST) $(WWWDST) $(CA_CERTS) $(COMMONKEEP)
all: bearssl libc libjpeg libjpegwrite tls libloader libs libhello $(TARGETS) fetch wiki wikipedia weather imageviewer fontpreview spreadsheet wordprocessor pdfviewer disks devexplorer installer volume music video bluetooth terminal klog procmgr calculator doom rpgdemo paint tcc lua screenshot texteditor mandelbrot printers printd printctl dialogs login desktop shell icons fonts install-apps test_dl $(MANDST) $(WWWDST) $(CA_CERTS) $(COMMONKEEP)
# Build BearSSL static library (cross-compiled for freestanding x86_64).
BEARSSL_INCLUDES := -isystem $(shell cd .. && pwd)/kernel/freestnd-c-hdrs/x86_64/include -isystem $(abspath include/libc)
@@ -112,6 +112,10 @@ libloader: libc
libs: libloader
$(MAKE) -C libs/libmath
# Build libhello shared GUI library.
libhello: libloader
$(MAKE) -C libs/libhello
# Build fetch via its own Makefile (depends on bearssl, libc, and tls).
fetch: bearssl libc tls
$(MAKE) -C src/fetch
@@ -348,4 +352,5 @@ clean:
$(MAKE) -C src/dialogs clean
$(MAKE) -C src/libloader clean
$(MAKE) -C libs/libmath clean
$(MAKE) -C libs/libhello clean
$(MAKE) -C src/test_dl clean
+1
View File
@@ -148,6 +148,7 @@ namespace Montauk {
static constexpr uint64_t SYS_LOAD_LIB = 114;
static constexpr uint64_t SYS_UNLOAD_LIB = 115;
static constexpr uint64_t SYS_DLSYM = 116;
static constexpr uint64_t SYS_GETLIBBASE = 117;
static constexpr uint32_t IPC_SIGNAL_READABLE = 1u << 0;
static constexpr uint32_t IPC_SIGNAL_WRITABLE = 1u << 1;
-39
View File
@@ -135,51 +135,12 @@ struct Canvas {
void text(int x, int y, const char* str, Color c) {
if (fonts::system_font && fonts::system_font->valid) {
fonts::system_font->draw_to_buffer(pixels, w, h, x, y, str, c, fonts::UI_SIZE);
return;
}
uint32_t px = c.to_pixel();
for (int i = 0; str[i] && x + (i + 1) * FONT_WIDTH <= w; i++) {
const uint8_t* glyph = &font_data[(unsigned char)str[i] * FONT_HEIGHT];
int cx = x + i * FONT_WIDTH;
for (int fy = 0; fy < FONT_HEIGHT && y + fy < h; fy++) {
uint8_t bits = glyph[fy];
for (int fx = 0; fx < FONT_WIDTH; fx++) {
if (bits & (0x80 >> fx)) {
int dx = cx + fx;
int dy = y + fy;
if (dx >= 0 && dx < w && dy >= 0)
pixels[dy * w + dx] = px;
}
}
}
}
}
void text_2x(int x, int y, const char* str, Color c) {
if (fonts::system_font && fonts::system_font->valid) {
fonts::system_font->draw_to_buffer(pixels, w, h, x, y, str, c, fonts::LARGE_SIZE);
return;
}
uint32_t px = c.to_pixel();
for (int i = 0; str[i] && x + (i + 1) * FONT_WIDTH * 2 <= w; i++) {
const uint8_t* glyph = &font_data[(unsigned char)str[i] * FONT_HEIGHT];
int cx = x + i * FONT_WIDTH * 2;
for (int fy = 0; fy < FONT_HEIGHT; fy++) {
uint8_t bits = glyph[fy];
for (int fx = 0; fx < FONT_WIDTH; fx++) {
if (bits & (0x80 >> fx)) {
int dx = cx + fx * 2;
int dy = y + fy * 2;
for (int sy = 0; sy < 2; sy++)
for (int sx = 0; sx < 2; sx++) {
int pdx = dx + sx;
int pdy = dy + sy;
if (pdx >= 0 && pdx < w && pdy >= 0 && pdy < h)
pixels[pdy * w + pdx] = px;
}
}
}
}
}
}
+3
View File
@@ -292,6 +292,9 @@ namespace montauk {
inline void* dlsym(int handle, uint64_t symbolOffset) {
return (void*)syscall2(Montauk::SYS_DLSYM, (uint64_t)handle, symbolOffset);
}
inline uint64_t get_libbase(int handle) {
return (uint64_t)syscall1(Montauk::SYS_GETLIBBASE, (uint64_t)handle);
}
// Process management
inline void waitpid(int pid) { syscall1(Montauk::SYS_WAITPID, (uint64_t)pid); }
+74
View File
@@ -0,0 +1,74 @@
# Makefile for libhello shared library
# Builds libhello.lib at fixed address 0x400000 (relocated at load time)
# Target architecture.
ARCH := x86_64
# Toolchain
TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf-
CXX := $(TOOLCHAIN_PREFIX)g++
NM := $(TOOLCHAIN_PREFIX)nm
STRIP := $(TOOLCHAIN_PREFIX)strip
# Compiler flags: freestanding, no stdlib
override CXXFLAGS := \
-std=gnu++20 \
-g -O2 -pipe \
-Wall \
-Wextra \
-nostdinc \
-ffreestanding \
-fno-stack-protector \
-fno-stack-check \
-fno-PIC \
-fno-rtti \
-fno-exceptions \
-ffunction-sections \
-fdata-sections \
-m64 \
-march=x86-64 \
-mno-80387 \
-mno-mmx \
-mno-red-zone \
-mcmodel=small \
-I ../../include \
-isystem ../../include/libc \
-isystem ../../include/montauk \
-isystem ../../include/gui \
-isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
# Linker flags: freestanding static ELF at fixed address
# Note: NOT using --gc-sections so all functions are kept
override LDFLAGS := \
-nostdlib \
-static \
-Wl,--build-id=none \
-Wl,-m,elf_x86_64 \
-T link.ld
# Output
OUTDIR := ../../bin/os
LIBNAME := libhello
LIBSRC := src/libhello.cpp
.PHONY: all clean
all: $(OUTDIR)/$(LIBNAME).lib $(OUTDIR)/$(LIBNAME).lib.sym
$(OUTDIR)/$(LIBNAME).lib: $(LIBSRC)
@mkdir -p $(OUTDIR)
$(CXX) $(CXXFLAGS) -c src/libhello.cpp -o src/libhello.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) src/libhello.o -o $@
# Generate symbol file from nm output
# Format: "symbol_name,offset_in_hex"
$(OUTDIR)/$(LIBNAME).lib.sym: $(OUTDIR)/$(LIBNAME).lib
@mkdir -p $(OUTDIR)
@echo "# Symbol table for $(LIBNAME)" > $@
@echo "# This file maps symbol names to offsets from library base" >> $@
@$(NM) $(OUTDIR)/$(LIBNAME).lib | grep ' T ' | awk '{printf "%s,0x%x\n", $$3, strtonum("0x" $$1) - 0x400000}' >> $@
@echo "Generated symbol file: $@"
clean:
rm -rf ../../bin/os/$(LIBNAME).lib ../../bin/os/$(LIBNAME).lib.sym src/libhello.o src/stb_truetype_impl.o
+13
View File
@@ -0,0 +1,13 @@
SECTIONS
{
. = 0x400000;
.text : {
*(.text)
}
.eh_frame : {
*(.eh_frame)
}
.rodata : {
*(.rodata)
}
}
+67
View File
@@ -0,0 +1,67 @@
/*
* libhello.cpp
* Sample shared GUI library for MontaukOS
* Creates a window and renders text as a demo of the shared library + GUI system
* Copyright (c) 2026 Daniel Hammer
*/
#include <montauk/syscall.h>
// Exported demo function - creates a window and renders until closed
extern "C" int hello_run() {
// Create window
Montauk::WinCreateResult wres;
if (montauk::win_create("libhello Demo", 320, 200, &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;
// 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;
}
}
// Present the initial frame
montauk::win_present(winId);
// Event loop
while (true) {
Montauk::WinEvent ev;
int r = montauk::win_poll(winId, &ev);
if (r < 0) {
break;
}
if (r == 0) {
montauk::sleep_ms(16);
continue;
}
if (ev.type == 3) { // close
break;
}
if (ev.type == 2) { // resize
width = ev.resize.w;
height = ev.resize.h;
pixels = (uint32_t*)(uintptr_t)montauk::win_resize(winId, width, height);
// Re-render on resize
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
pixels[y * width + x] = 0xFF1a1a2e;
}
}
montauk::win_present(winId);
}
}
montauk::win_destroy(winId);
return 0;
}
Binary file not shown.
@@ -0,0 +1,33 @@
/*
* stb_truetype_impl.cpp
* Single compilation unit for stb_truetype in libhello
* Copyright (c) 2026 Daniel Hammer
*/
#include <cstdint>
#include <cstddef>
#include <montauk/heap.h>
#include <montauk/string.h>
#include <gui/stb_math.h>
#define STBTT_ifloor(x) ((int) stb_floor(x))
#define STBTT_iceil(x) ((int) stb_ceil(x))
#define STBTT_sqrt(x) stb_sqrt(x)
#define STBTT_pow(x,y) stb_pow(x,y)
#define STBTT_fmod(x,y) stb_fmod(x,y)
#define STBTT_cos(x) stb_cos(x)
#define STBTT_acos(x) stb_acos(x)
#define STBTT_fabs(x) stb_fabs(x)
#define STBTT_malloc(x,u) ((void)(u), montauk::malloc(x))
#define STBTT_free(x,u) ((void)(u), montauk::mfree(x))
#define STBTT_memcpy(d,s,n) montauk::memcpy(d,s,n)
#define STBTT_memset(d,v,n) montauk::memset(d,v,n)
#define STBTT_strlen(x) montauk::slen(x)
#define STBTT_assert(x) ((void)(x))
#define STB_TRUETYPE_IMPLEMENTATION
#include <gui/stb_truetype.h>
+6 -7
View File
@@ -107,6 +107,10 @@ static bool parseSymbolFile(const char* symPath, LibHandle* lib) {
static uint64_t hexToUint64(const char* str) {
uint64_t result = 0;
// Skip optional "0x" prefix
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
str += 2;
}
while (*str) {
char c = *str;
uint64_t val = 0;
@@ -164,14 +168,9 @@ LibHandle* dlopen(const char* path) {
void* dlsym(LibHandle* lib, const char* symbolName) {
if (!lib || !symbolName) return nullptr;
// Get base address if we don't have it
// Get base address from kernel if we don't have it
if (lib->base == 0) {
// The base is stored in the handle - we need a syscall to get it
// For now, we'll use a workaround: calculate base from slot
// handle = slot + 1, so slot = handle - 1
// base = 0x60000000 + slot * 0x200000
int slot = lib->handle - 1;
lib->base = 0x60000000ULL + (uint64_t)slot * 0x200000ULL;
lib->base = montauk::get_libbase(lib->handle);
}
// Look up in symbol table
+57 -1
View File
@@ -7,8 +7,9 @@
#include <montauk/syscall.h>
#include <libloader/libloader.h>
// Forward declaration
// Forward declarations
static void print_int(int val);
static void print_hex(uint64_t val);
extern "C" void _start() {
montauk::print("=== Dynamic Library Test ===\n\n");
@@ -78,6 +79,39 @@ extern "C" void _start() {
libloader::dlclose(lib);
montauk::print("Library unloaded.\n");
// Test loading libhello (GUI library)
montauk::print("\nLoading libhello (GUI library)...\n");
LibHandle* hellolib = libloader::dlopen("0:/os/libhello.lib");
if (!hellolib) {
montauk::print("ERROR: Failed to load libhello.lib\n");
montauk::exit(1);
}
montauk::print("Library loaded successfully!\n\n");
// Resolve hello_run
typedef int (*hello_run_t)(void);
hello_run_t hello_run = (hello_run_t)libloader::dlsym(hellolib, "hello_run");
if (!hello_run) {
montauk::print("ERROR: Failed to resolve hello_run\n");
montauk::exit(1);
}
montauk::print(" hello_run: OK\n\n");
// Debug: print hello_run address
montauk::print(" DEBUG: hello_run @ ");
print_hex((uint64_t)hello_run);
montauk::print("\n");
// Run the GUI demo (this creates a window and event loop)
montauk::print("Running GUI demo...\n");
hello_run();
// Unload the library
montauk::print("GUI demo closed.\n");
montauk::print("Unloading library...\n");
libloader::dlclose(hellolib);
montauk::print("Library unloaded.\n");
montauk::print("\n=== All tests passed! ===\n");
montauk::exit(0);
}
@@ -110,3 +144,25 @@ static void print_int(int val) {
montauk::putchar(buf[i]);
}
}
// Print hex value (uppercase, with 0x prefix)
static void print_hex(uint64_t val) {
montauk::print("0x");
char buf[20];
int idx = 0;
if (val == 0) {
buf[idx++] = '0';
} else {
while (val > 0) {
int digit = val & 0xF;
buf[idx++] = (digit < 10) ? ('0' + digit) : ('A' + digit - 10);
val >>= 4;
}
}
// Reverse the buffer
for (int i = idx - 1; i >= 0; i--) {
montauk::putchar(buf[i]);
}
}