wip: extend shared library support, window demo
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,13 @@
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x400000;
|
||||
.text : {
|
||||
*(.text)
|
||||
}
|
||||
.eh_frame : {
|
||||
*(.eh_frame)
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user