wip: shared library support
This commit is contained in:
+18
-3
@@ -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
|
||||
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
|
||||
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
|
||||
.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
|
||||
|
||||
all: bearssl libc libjpeg libjpegwrite tls $(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 $(MANDST) $(WWWDST) $(CA_CERTS) $(COMMONKEEP)
|
||||
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)
|
||||
|
||||
# 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)
|
||||
@@ -104,6 +104,14 @@ libc:
|
||||
tls: bearssl libc
|
||||
$(MAKE) -C lib/tls
|
||||
|
||||
# Build libloader static library (used by test_dl).
|
||||
libloader: libc
|
||||
$(MAKE) -C src/libloader
|
||||
|
||||
# Build shared libraries (libmath.lib etc).
|
||||
libs: libloader
|
||||
$(MAKE) -C libs/libmath
|
||||
|
||||
# Build fetch via its own Makefile (depends on bearssl, libc, and tls).
|
||||
fetch: bearssl libc tls
|
||||
$(MAKE) -C src/fetch
|
||||
@@ -265,6 +273,10 @@ printctl: bearssl libc tls
|
||||
dialogs: bearssl libc tls
|
||||
$(MAKE) -C src/dialogs
|
||||
|
||||
# Build test_dl (dynamic loading test app, depends on libloader).
|
||||
test_dl: libloader libs
|
||||
$(MAKE) -C src/test_dl
|
||||
|
||||
# Install app bundles (manifests, icons, data files) into bin/apps/<name>/.
|
||||
install-apps: doom rpgdemo paint spreadsheet wordprocessor weather wikipedia imageviewer fontpreview pdfviewer disks devexplorer installer volume music video bluetooth terminal klog procmgr calculator screenshot texteditor mandelbrot printers dialogs
|
||||
../scripts/install_apps.sh
|
||||
@@ -334,3 +346,6 @@ clean:
|
||||
$(MAKE) -C src/printd clean
|
||||
$(MAKE) -C src/printctl clean
|
||||
$(MAKE) -C src/dialogs clean
|
||||
$(MAKE) -C src/libloader clean
|
||||
$(MAKE) -C libs/libmath clean
|
||||
$(MAKE) -C src/test_dl clean
|
||||
|
||||
@@ -144,6 +144,11 @@ namespace Montauk {
|
||||
static constexpr uint64_t SYS_SURFACE_MAP = 112;
|
||||
static constexpr uint64_t SYS_SURFACE_RESIZE = 113;
|
||||
|
||||
// Shared library syscalls
|
||||
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 uint32_t IPC_SIGNAL_READABLE = 1u << 0;
|
||||
static constexpr uint32_t IPC_SIGNAL_WRITABLE = 1u << 1;
|
||||
static constexpr uint32_t IPC_SIGNAL_PEER_CLOSED = 1u << 2;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* libloader.h
|
||||
* Dynamic library loading interface for MontaukOS
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <montauk/syscall.h>
|
||||
|
||||
// Library handle - opaque to users
|
||||
struct LibHandle {
|
||||
int handle; // syscall handle (slot + 1)
|
||||
uint64_t base; // base virtual address
|
||||
char path[256];
|
||||
int symbolCount;
|
||||
struct SymbolEntry {
|
||||
char name[64];
|
||||
uint64_t offset;
|
||||
}* symbols;
|
||||
};
|
||||
|
||||
namespace libloader {
|
||||
|
||||
// Maximum libraries that can be loaded per process
|
||||
static constexpr int MaxLoadedLibs = 8;
|
||||
|
||||
// Load a shared library.
|
||||
// Returns a LibHandle* on success, or nullptr on failure.
|
||||
LibHandle* dlopen(const char* path);
|
||||
|
||||
// Look up a symbol in a loaded library.
|
||||
// Returns the function/data pointer, or nullptr if not found.
|
||||
void* dlsym(LibHandle* lib, const char* symbolName);
|
||||
|
||||
// Unload a library.
|
||||
// Returns 0 on success, -1 on failure.
|
||||
int dlclose(LibHandle* lib);
|
||||
|
||||
} // namespace libloader
|
||||
@@ -282,6 +282,17 @@ namespace montauk {
|
||||
return (int)syscall2(Montauk::SYS_SURFACE_RESIZE, (uint64_t)handle, newSize);
|
||||
}
|
||||
|
||||
// Shared library support
|
||||
inline int load_lib(const char* path) {
|
||||
return (int)syscall1(Montauk::SYS_LOAD_LIB, (uint64_t)path);
|
||||
}
|
||||
inline int unload_lib(int handle) {
|
||||
return (int)syscall1(Montauk::SYS_UNLOAD_LIB, (uint64_t)handle);
|
||||
}
|
||||
inline void* dlsym(int handle, uint64_t symbolOffset) {
|
||||
return (void*)syscall2(Montauk::SYS_DLSYM, (uint64_t)handle, symbolOffset);
|
||||
}
|
||||
|
||||
// Process management
|
||||
inline void waitpid(int pid) { syscall1(Montauk::SYS_WAITPID, (uint64_t)pid); }
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
# Makefile for libmath shared library
|
||||
# Builds libmath.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-sse \
|
||||
-mno-sse2 \
|
||||
-mno-red-zone \
|
||||
-mcmodel=small \
|
||||
-I ../../include \
|
||||
-isystem ../../include/libc \
|
||||
-isystem ../../include/montauk
|
||||
|
||||
# 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 := libmath
|
||||
LIBSRC := src/libmath.cpp
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(OUTDIR)/$(LIBNAME).lib $(OUTDIR)/$(LIBNAME).lib.sym
|
||||
|
||||
$(OUTDIR)/$(LIBNAME).lib: $(LIBSRC)
|
||||
@mkdir -p $(OUTDIR)
|
||||
$(CXX) $(CXXFLAGS) -c $(LIBSRC) -o src/libmath.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) src/libmath.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/libmath.o
|
||||
@@ -0,0 +1,10 @@
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x400000;
|
||||
.text : {
|
||||
*(.text)
|
||||
}
|
||||
.eh_frame : {
|
||||
*(.eh_frame)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* libmath.cpp
|
||||
* Sample shared math library for MontaukOS
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Basic math functions
|
||||
|
||||
int math_add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int math_sub(int a, int b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
int math_mul(int a, int b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
int math_div(int a, int b) {
|
||||
if (b == 0) return 0;
|
||||
return a / b;
|
||||
}
|
||||
|
||||
int math_mod(int a, int b) {
|
||||
if (b == 0) return 0;
|
||||
return a % b;
|
||||
}
|
||||
|
||||
// Comparison
|
||||
int math_max(int a, int b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
int math_min(int a, int b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
int math_abs(int a) {
|
||||
return (a < 0) ? -a : a;
|
||||
}
|
||||
|
||||
// Utility
|
||||
int math_pow(int base, int exp) {
|
||||
int result = 1;
|
||||
for (int i = 0; i < exp; i++) {
|
||||
result *= base;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
Binary file not shown.
@@ -0,0 +1,50 @@
|
||||
# Makefile for libloader
|
||||
|
||||
ARCH := x86_64
|
||||
|
||||
TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf-
|
||||
CXX := $(TOOLCHAIN_PREFIX)g++
|
||||
AR := $(TOOLCHAIN_PREFIX)ar
|
||||
|
||||
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-sse \
|
||||
-mno-sse2 \
|
||||
-mno-red-zone \
|
||||
-mcmodel=small \
|
||||
-I ../../include \
|
||||
-isystem ../../include/libc \
|
||||
-isystem ../../include/montauk \
|
||||
-isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \
|
||||
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
|
||||
|
||||
BINDIR := ../../bin
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(BINDIR)/liblibloader.a
|
||||
|
||||
$(BINDIR)/liblibloader.a: libloader.cpp
|
||||
@mkdir -p $(BINDIR)
|
||||
$(CXX) $(CXXFLAGS) -c libloader.cpp -o libloader.o
|
||||
$(AR) rcs $(BINDIR)/liblibloader.a libloader.o
|
||||
rm -f libloader.o
|
||||
|
||||
clean:
|
||||
rm -f $(BINDIR)/liblibloader.a
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* libloader.cpp
|
||||
* Dynamic library loading implementation for MontaukOS
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*/
|
||||
|
||||
#include <libloader/libloader.h>
|
||||
#include <montauk/syscall.h>
|
||||
#include <libc/string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace libloader {
|
||||
|
||||
// Forward declaration
|
||||
static uint64_t hexToUint64(const char* str);
|
||||
|
||||
// Table of currently loaded libraries
|
||||
static LibHandle g_loadedLibs[MaxLoadedLibs];
|
||||
static int g_libCount = 0;
|
||||
|
||||
static LibHandle* findLoadedLib(const char* path) {
|
||||
for (int i = 0; i < g_libCount; i++) {
|
||||
if (g_loadedLibs[i].handle > 0 &&
|
||||
strcmp(g_loadedLibs[i].path, path) == 0) {
|
||||
return &g_loadedLibs[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool parseSymbolFile(const char* symPath, LibHandle* lib) {
|
||||
int fd = montauk::open(symPath);
|
||||
if (fd < 0) {
|
||||
// No symbol file - that's okay, we'll still load the lib
|
||||
lib->symbolCount = 0;
|
||||
lib->symbols = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t size = montauk::getsize(fd);
|
||||
if (size == 0 || size > 65536) {
|
||||
montauk::close(fd);
|
||||
lib->symbolCount = 0;
|
||||
lib->symbols = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
char* buf = (char*)montauk::alloc(size + 1);
|
||||
if (!buf) {
|
||||
montauk::close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
int read = montauk::read(fd, (uint8_t*)buf, 0, size);
|
||||
montauk::close(fd);
|
||||
if (read != (int)size) {
|
||||
montauk::free(buf);
|
||||
return false;
|
||||
}
|
||||
buf[size] = '\0';
|
||||
|
||||
// Count lines first
|
||||
int lineCount = 0;
|
||||
for (uint64_t i = 0; i < size; i++) {
|
||||
if (buf[i] == '\n') lineCount++;
|
||||
}
|
||||
|
||||
if (lineCount == 0) {
|
||||
montauk::free(buf);
|
||||
lib->symbolCount = 0;
|
||||
lib->symbols = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
lib->symbols = (LibHandle::SymbolEntry*)montauk::alloc(lineCount * sizeof(LibHandle::SymbolEntry));
|
||||
if (!lib->symbols) {
|
||||
montauk::free(buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
lib->symbolCount = lineCount;
|
||||
|
||||
// Parse lines: "symbol_name,offset_hex"
|
||||
int entryIdx = 0;
|
||||
char* lineStart = buf;
|
||||
for (uint64_t i = 0; i <= size; i++) {
|
||||
if (buf[i] == '\n' || buf[i] == '\0') {
|
||||
buf[i] = '\0';
|
||||
char* comma = strchr(lineStart, ',');
|
||||
if (comma && entryIdx < lineCount) {
|
||||
size_t nameLen = comma - lineStart;
|
||||
if (nameLen < sizeof(lib->symbols[0].name) - 1) {
|
||||
memcpy(lib->symbols[entryIdx].name, lineStart, nameLen);
|
||||
lib->symbols[entryIdx].name[nameLen] = '\0';
|
||||
lib->symbols[entryIdx].offset = hexToUint64(comma + 1);
|
||||
entryIdx++;
|
||||
}
|
||||
}
|
||||
lineStart = &buf[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
lib->symbolCount = entryIdx;
|
||||
montauk::free(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint64_t hexToUint64(const char* str) {
|
||||
uint64_t result = 0;
|
||||
while (*str) {
|
||||
char c = *str;
|
||||
uint64_t val = 0;
|
||||
if (c >= '0' && c <= '9') val = c - '0';
|
||||
else if (c >= 'a' && c <= 'f') val = c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F') val = c - 'A' + 10;
|
||||
else break;
|
||||
result = (result << 4) | val;
|
||||
str++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
LibHandle* dlopen(const char* path) {
|
||||
if (!path) return nullptr;
|
||||
|
||||
// Check if already loaded
|
||||
LibHandle* existing = findLoadedLib(path);
|
||||
if (existing) {
|
||||
// Just return existing handle
|
||||
return existing;
|
||||
}
|
||||
|
||||
if (g_libCount >= MaxLoadedLibs) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Load the library via syscall
|
||||
int handle = montauk::load_lib(path);
|
||||
if (handle <= 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create symbol file path: append ".sym"
|
||||
char symPath[320];
|
||||
size_t pathLen = strlen(path);
|
||||
if (pathLen >= sizeof(symPath) - 5) return nullptr;
|
||||
|
||||
strcpy(symPath, path);
|
||||
strcpy(symPath + pathLen, ".sym");
|
||||
|
||||
LibHandle* lib = &g_loadedLibs[g_libCount++];
|
||||
lib->handle = handle;
|
||||
lib->base = 0; // Will be retrieved on first dlsym
|
||||
strcpy(lib->path, path);
|
||||
lib->symbolCount = 0;
|
||||
lib->symbols = nullptr;
|
||||
|
||||
// Parse symbol file
|
||||
parseSymbolFile(symPath, lib);
|
||||
|
||||
return lib;
|
||||
}
|
||||
|
||||
void* dlsym(LibHandle* lib, const char* symbolName) {
|
||||
if (!lib || !symbolName) return nullptr;
|
||||
|
||||
// Get base address 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;
|
||||
}
|
||||
|
||||
// Look up in symbol table
|
||||
for (int i = 0; i < lib->symbolCount; i++) {
|
||||
if (strcmp(lib->symbols[i].name, symbolName) == 0) {
|
||||
uint64_t offset = lib->symbols[i].offset;
|
||||
return (void*)montauk::dlsym(lib->handle, offset);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr; // Symbol not found
|
||||
}
|
||||
|
||||
int dlclose(LibHandle* lib) {
|
||||
if (!lib) return -1;
|
||||
|
||||
int result = montauk::unload_lib(lib->handle);
|
||||
if (result == 0) {
|
||||
// Free symbol table if allocated
|
||||
if (lib->symbols) {
|
||||
montauk::free((void*)lib->symbols);
|
||||
lib->symbols = nullptr;
|
||||
}
|
||||
lib->handle = 0;
|
||||
lib->base = 0;
|
||||
lib->symbolCount = 0;
|
||||
lib->path[0] = '\0';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace libloader
|
||||
@@ -0,0 +1,60 @@
|
||||
# Makefile for test_dl
|
||||
|
||||
ARCH := x86_64
|
||||
|
||||
TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf-
|
||||
CXX := $(TOOLCHAIN_PREFIX)g++
|
||||
|
||||
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-sse \
|
||||
-mno-sse2 \
|
||||
-mno-red-zone \
|
||||
-mcmodel=small \
|
||||
-I ../../include \
|
||||
-isystem ../../include/libc \
|
||||
-isystem ../../include/montauk \
|
||||
-isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \
|
||||
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
|
||||
|
||||
override LDFLAGS := \
|
||||
-nostdlib \
|
||||
-static \
|
||||
-Wl,--build-id=none \
|
||||
-Wl,--gc-sections \
|
||||
-Wl,-m,elf_x86_64 \
|
||||
-z max-page-size=0x1000 \
|
||||
-T ../../link.ld
|
||||
|
||||
BINDIR := ../../bin/os
|
||||
LIBDIR := ../../bin
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(BINDIR)/test_dl.elf
|
||||
|
||||
$(BINDIR)/test_dl.elf: main.cpp
|
||||
@mkdir -p $(BINDIR)
|
||||
$(CXX) $(CXXFLAGS) -c main.cpp -o main.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) main.o $(LIBDIR)/liblibloader.a ../../lib/libc/liblibc.a -o $@
|
||||
rm -f main.o
|
||||
rm -f $(LIBDIR)/liblibloader.a
|
||||
|
||||
clean:
|
||||
rm -f $(BINDIR)/test_dl.elf
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* test_dl.cpp
|
||||
* Test application for dynamic library loading
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*/
|
||||
|
||||
#include <montauk/syscall.h>
|
||||
#include <libloader/libloader.h>
|
||||
|
||||
// Forward declaration
|
||||
static void print_int(int val);
|
||||
|
||||
extern "C" void _start() {
|
||||
montauk::print("=== Dynamic Library Test ===\n\n");
|
||||
|
||||
// Test loading libmath
|
||||
montauk::print("Loading libmath...\n");
|
||||
LibHandle* lib = libloader::dlopen("0:/os/libmath.lib");
|
||||
if (!lib) {
|
||||
montauk::print("ERROR: Failed to load libmath.lib\n");
|
||||
montauk::exit(1);
|
||||
}
|
||||
montauk::print("Library loaded successfully!\n\n");
|
||||
|
||||
// Test dlsym for various functions
|
||||
montauk::print("Resolving symbols...\n");
|
||||
|
||||
// math_add
|
||||
typedef int (*math_fn_t)(int, int);
|
||||
math_fn_t math_add = (math_fn_t)libloader::dlsym(lib, "math_add");
|
||||
if (!math_add) {
|
||||
montauk::print("ERROR: Failed to resolve math_add\n");
|
||||
montauk::exit(1);
|
||||
}
|
||||
montauk::print(" math_add: OK\n");
|
||||
|
||||
// math_mul
|
||||
math_fn_t math_mul = (math_fn_t)libloader::dlsym(lib, "math_mul");
|
||||
if (!math_mul) {
|
||||
montauk::print("ERROR: Failed to resolve math_mul\n");
|
||||
montauk::exit(1);
|
||||
}
|
||||
montauk::print(" math_mul: OK\n");
|
||||
|
||||
// math_max
|
||||
typedef int (*math_max_t)(int, int);
|
||||
math_max_t math_max = (math_max_t)libloader::dlsym(lib, "math_max");
|
||||
if (!math_max) {
|
||||
montauk::print("ERROR: Failed to resolve math_max\n");
|
||||
montauk::exit(1);
|
||||
}
|
||||
montauk::print(" math_max: OK\n\n");
|
||||
|
||||
// Test the functions
|
||||
montauk::print("Testing library functions:\n");
|
||||
|
||||
// Test add: 10 + 5 = 15
|
||||
int a = 10, b = 5;
|
||||
int result = math_add(a, b);
|
||||
montauk::print(" math_add(10, 5) = ");
|
||||
print_int(result);
|
||||
montauk::print("\n");
|
||||
|
||||
// Test mul: 7 * 6 = 42
|
||||
result = math_mul(7, 6);
|
||||
montauk::print(" math_mul(7, 6) = ");
|
||||
print_int(result);
|
||||
montauk::print("\n");
|
||||
|
||||
// Test max: max(100, 200) = 200
|
||||
result = math_max(100, 200);
|
||||
montauk::print(" math_max(100, 200) = ");
|
||||
print_int(result);
|
||||
montauk::print("\n\n");
|
||||
|
||||
// Unload the library
|
||||
montauk::print("Unloading library...\n");
|
||||
libloader::dlclose(lib);
|
||||
montauk::print("Library unloaded.\n");
|
||||
|
||||
montauk::print("\n=== All tests passed! ===\n");
|
||||
montauk::exit(0);
|
||||
}
|
||||
|
||||
// Simple integer to string conversion for printing
|
||||
static void print_int(int val) {
|
||||
char buf[16];
|
||||
int idx = 0;
|
||||
bool neg = false;
|
||||
|
||||
if (val < 0) {
|
||||
neg = true;
|
||||
val = -val;
|
||||
}
|
||||
|
||||
if (val == 0) {
|
||||
buf[idx++] = '0';
|
||||
} else {
|
||||
while (val > 0) {
|
||||
buf[idx++] = '0' + (val % 10);
|
||||
val /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (neg) {
|
||||
montauk::putchar('-');
|
||||
}
|
||||
|
||||
for (int i = idx - 1; i >= 0; i--) {
|
||||
montauk::putchar(buf[i]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user