动态链接库+修复神秘光标问题

This commit is contained in:
2026-04-18 13:52:36 +08:00
parent 8e968af551
commit 6a93335e53
12 changed files with 642 additions and 11 deletions

View File

@@ -0,0 +1,48 @@
#include <dlfcn.h>
#include <stdio.h>
typedef unsigned long long u64;
typedef u64 (*dl_math2_fn)(u64, u64);
typedef u64 (*dl_void_fn)(void);
int cleonos_app_main(int argc, char **argv, char **envp) {
const char *lib_path = "/shell/libdemo.elf";
void *handle;
dl_math2_fn add_fn;
dl_math2_fn mul_fn;
dl_void_fn hello_fn;
(void)envp;
if (argc > 1 && argv != (char **)0 && argv[1] != (char *)0 && argv[1][0] != '\0') {
lib_path = argv[1];
}
handle = dlopen(lib_path, 0);
if (handle == (void *)0) {
(void)printf("[dltest] dlopen failed: %s\n", lib_path);
return 1;
}
add_fn = (dl_math2_fn)dlsym(handle, "cleonos_libdemo_add");
mul_fn = (dl_math2_fn)dlsym(handle, "cleonos_libdemo_mul");
hello_fn = (dl_void_fn)dlsym(handle, "cleonos_libdemo_hello");
if (add_fn == (dl_math2_fn)0 || mul_fn == (dl_math2_fn)0 || hello_fn == (dl_void_fn)0) {
(void)puts("[dltest] dlsym failed");
(void)dlclose(handle);
return 2;
}
(void)hello_fn();
(void)printf("[dltest] add(7, 35) = %llu\n", add_fn(7ULL, 35ULL));
(void)printf("[dltest] mul(6, 9) = %llu\n", mul_fn(6ULL, 9ULL));
if (dlclose(handle) != 0) {
(void)puts("[dltest] dlclose failed");
return 3;
}
(void)puts("[dltest] PASS");
return 0;
}

View File

@@ -0,0 +1,24 @@
#include <stdio.h>
typedef unsigned long long u64;
u64 cleonos_libdemo_add(u64 left, u64 right) {
return left + right;
}
u64 cleonos_libdemo_mul(u64 left, u64 right) {
return left * right;
}
u64 cleonos_libdemo_hello(void) {
(void)puts("[libdemo] hello from libdemo.elf");
return 0ULL;
}
int cleonos_app_main(int argc, char **argv, char **envp) {
(void)argc;
(void)argv;
(void)envp;
(void)puts("[libdemo] dynamic library image ready");
return 0;
}

View File

@@ -119,6 +119,9 @@ typedef struct cleonos_proc_snapshot {
#define CLEONOS_SYSCALL_FD_WRITE 74ULL #define CLEONOS_SYSCALL_FD_WRITE 74ULL
#define CLEONOS_SYSCALL_FD_CLOSE 75ULL #define CLEONOS_SYSCALL_FD_CLOSE 75ULL
#define CLEONOS_SYSCALL_FD_DUP 76ULL #define CLEONOS_SYSCALL_FD_DUP 76ULL
#define CLEONOS_SYSCALL_DL_OPEN 77ULL
#define CLEONOS_SYSCALL_DL_CLOSE 78ULL
#define CLEONOS_SYSCALL_DL_SYM 79ULL
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
u64 cleonos_sys_log_write(const char *message, u64 length); u64 cleonos_sys_log_write(const char *message, u64 length);
@@ -197,5 +200,8 @@ u64 cleonos_sys_fd_read(u64 fd, void *out_buffer, u64 size);
u64 cleonos_sys_fd_write(u64 fd, const void *buffer, u64 size); u64 cleonos_sys_fd_write(u64 fd, const void *buffer, u64 size);
u64 cleonos_sys_fd_close(u64 fd); u64 cleonos_sys_fd_close(u64 fd);
u64 cleonos_sys_fd_dup(u64 fd); u64 cleonos_sys_fd_dup(u64 fd);
u64 cleonos_sys_dl_open(const char *path);
u64 cleonos_sys_dl_close(u64 handle);
u64 cleonos_sys_dl_sym(u64 handle, const char *symbol);
#endif #endif

View File

@@ -0,0 +1,8 @@
#ifndef CLEONOS_LIBC_DLFCN_H
#define CLEONOS_LIBC_DLFCN_H
void *dlopen(const char *path, int flags);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);
#endif

48
cleonos/c/src/dlfcn.c Normal file
View File

@@ -0,0 +1,48 @@
#include <dlfcn.h>
#include <cleonos_syscall.h>
void *dlopen(const char *path, int flags) {
u64 handle;
(void)flags;
if (path == (const char *)0 || path[0] == '\0') {
return (void *)0;
}
handle = cleonos_sys_dl_open(path);
if (handle == 0ULL || handle == (u64)-1) {
return (void *)0;
}
return (void *)handle;
}
void *dlsym(void *handle, const char *symbol) {
u64 addr;
if (handle == (void *)0 || symbol == (const char *)0 || symbol[0] == '\0') {
return (void *)0;
}
addr = cleonos_sys_dl_sym((u64)handle, symbol);
if (addr == 0ULL || addr == (u64)-1) {
return (void *)0;
}
return (void *)addr;
}
int dlclose(void *handle) {
u64 rc;
if (handle == (void *)0) {
return -1;
}
rc = cleonos_sys_dl_close((u64)handle);
return (rc == (u64)-1) ? -1 : 0;
}

View File

@@ -330,3 +330,15 @@ u64 cleonos_sys_fd_close(u64 fd) {
u64 cleonos_sys_fd_dup(u64 fd) { u64 cleonos_sys_fd_dup(u64 fd) {
return cleonos_syscall(CLEONOS_SYSCALL_FD_DUP, fd, 0ULL, 0ULL); return cleonos_syscall(CLEONOS_SYSCALL_FD_DUP, fd, 0ULL, 0ULL);
} }
u64 cleonos_sys_dl_open(const char *path) {
return cleonos_syscall(CLEONOS_SYSCALL_DL_OPEN, (u64)path, 0ULL, 0ULL);
}
u64 cleonos_sys_dl_close(u64 handle) {
return cleonos_syscall(CLEONOS_SYSCALL_DL_CLOSE, handle, 0ULL, 0ULL);
}
u64 cleonos_sys_dl_sym(u64 handle, const char *symbol) {
return cleonos_syscall(CLEONOS_SYSCALL_DL_SYM, handle, (u64)symbol, 0ULL);
}

View File

@@ -45,6 +45,9 @@ u64 clks_exec_fd_read(u64 fd, void *out_buffer, u64 size);
u64 clks_exec_fd_write(u64 fd, const void *buffer, u64 size); u64 clks_exec_fd_write(u64 fd, const void *buffer, u64 size);
u64 clks_exec_fd_close(u64 fd); u64 clks_exec_fd_close(u64 fd);
u64 clks_exec_fd_dup(u64 fd); u64 clks_exec_fd_dup(u64 fd);
u64 clks_exec_dl_open(const char *path);
u64 clks_exec_dl_close(u64 handle);
u64 clks_exec_dl_sym(u64 handle, const char *symbol);
u64 clks_exec_current_pid(void); u64 clks_exec_current_pid(void);
u32 clks_exec_current_tty(void); u32 clks_exec_current_tty(void);
u64 clks_exec_current_argc(void); u64 clks_exec_current_argc(void);

View File

@@ -80,6 +80,9 @@
#define CLKS_SYSCALL_FD_WRITE 74ULL #define CLKS_SYSCALL_FD_WRITE 74ULL
#define CLKS_SYSCALL_FD_CLOSE 75ULL #define CLKS_SYSCALL_FD_CLOSE 75ULL
#define CLKS_SYSCALL_FD_DUP 76ULL #define CLKS_SYSCALL_FD_DUP 76ULL
#define CLKS_SYSCALL_DL_OPEN 77ULL
#define CLKS_SYSCALL_DL_CLOSE 78ULL
#define CLKS_SYSCALL_DL_SYM 79ULL
void clks_syscall_init(void); void clks_syscall_init(void);
u64 clks_syscall_dispatch(void *frame_ptr); u64 clks_syscall_dispatch(void *frame_ptr);

View File

@@ -5,6 +5,7 @@
void clks_tty_init(void); void clks_tty_init(void);
void clks_tty_write(const char *text); void clks_tty_write(const char *text);
void clks_tty_write_n(const char *text, usize len);
void clks_tty_write_char(char ch); void clks_tty_write_char(char ch);
void clks_tty_switch(u32 tty_index); void clks_tty_switch(u32 tty_index);
void clks_tty_tick(u64 tick); void clks_tty_tick(u64 tick);

View File

@@ -34,6 +34,21 @@ typedef u64 (*clks_exec_entry_fn)(void);
#define CLKS_EXEC_O_CREAT 0x0040ULL #define CLKS_EXEC_O_CREAT 0x0040ULL
#define CLKS_EXEC_O_TRUNC 0x0200ULL #define CLKS_EXEC_O_TRUNC 0x0200ULL
#define CLKS_EXEC_O_APPEND 0x0400ULL #define CLKS_EXEC_O_APPEND 0x0400ULL
#define CLKS_EXEC_DYNLIB_MAX 32U
#define CLKS_EXEC_ELF64_MAGIC_0 0x7FU
#define CLKS_EXEC_ELF64_MAGIC_1 'E'
#define CLKS_EXEC_ELF64_MAGIC_2 'L'
#define CLKS_EXEC_ELF64_MAGIC_3 'F'
#define CLKS_EXEC_ELF64_CLASS_64 2U
#define CLKS_EXEC_ELF64_DATA_LSB 1U
#define CLKS_EXEC_ELF64_VERSION 1U
#define CLKS_EXEC_ELF64_SHT_SYMTAB 2U
#define CLKS_EXEC_ELF64_SHT_DYNSYM 11U
#define CLKS_EXEC_ELF64_SHN_UNDEF 0U
#define CLKS_EXEC_ELF64_STT_NOTYPE 0U
#define CLKS_EXEC_ELF64_STT_FUNC 2U
enum clks_exec_fd_kind { enum clks_exec_fd_kind {
CLKS_EXEC_FD_KIND_NONE = 0, CLKS_EXEC_FD_KIND_NONE = 0,
@@ -84,6 +99,56 @@ struct clks_exec_proc_record {
struct clks_exec_fd_entry fds[CLKS_EXEC_FD_MAX]; struct clks_exec_fd_entry fds[CLKS_EXEC_FD_MAX];
}; };
struct clks_exec_elf64_ehdr {
u8 e_ident[16];
u16 e_type;
u16 e_machine;
u32 e_version;
u64 e_entry;
u64 e_phoff;
u64 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
};
struct clks_exec_elf64_shdr {
u32 sh_name;
u32 sh_type;
u64 sh_flags;
u64 sh_addr;
u64 sh_offset;
u64 sh_size;
u32 sh_link;
u32 sh_info;
u64 sh_addralign;
u64 sh_entsize;
};
struct clks_exec_elf64_sym {
u32 st_name;
u8 st_info;
u8 st_other;
u16 st_shndx;
u64 st_value;
u64 st_size;
};
struct clks_exec_dynlib_slot {
clks_bool used;
u64 handle;
u64 owner_pid;
u64 ref_count;
char path[CLKS_EXEC_PATH_MAX];
const void *file_image;
u64 file_size;
struct clks_elf64_loaded_image loaded;
};
#if defined(CLKS_ARCH_X86_64) #if defined(CLKS_ARCH_X86_64)
extern u64 clks_exec_call_on_stack_x86_64(void *entry_ptr, void *stack_top); extern u64 clks_exec_call_on_stack_x86_64(void *entry_ptr, void *stack_top);
extern void clks_exec_abort_to_caller_x86_64(void); extern void clks_exec_abort_to_caller_x86_64(void);
@@ -105,6 +170,8 @@ static clks_bool clks_exec_unwind_slot_valid_stack[CLKS_EXEC_MAX_DEPTH];
static u64 clks_exec_image_begin_stack[CLKS_EXEC_MAX_DEPTH]; static u64 clks_exec_image_begin_stack[CLKS_EXEC_MAX_DEPTH];
static u64 clks_exec_image_end_stack[CLKS_EXEC_MAX_DEPTH]; static u64 clks_exec_image_end_stack[CLKS_EXEC_MAX_DEPTH];
static u32 clks_exec_pid_stack_depth = 0U; static u32 clks_exec_pid_stack_depth = 0U;
static struct clks_exec_dynlib_slot clks_exec_dynlib_table[CLKS_EXEC_DYNLIB_MAX];
static u64 clks_exec_next_dynlib_handle = 1ULL;
static struct clks_exec_proc_record *clks_exec_current_proc(void); static struct clks_exec_proc_record *clks_exec_current_proc(void);
@@ -263,6 +330,267 @@ static void clks_exec_copy_line(char *dst, usize dst_size, const char *src) {
dst[i] = '\0'; dst[i] = '\0';
} }
static clks_bool clks_exec_range_ok(u64 off, u64 len, u64 total) {
if (off > total) {
return CLKS_FALSE;
}
if (len > (total - off)) {
return CLKS_FALSE;
}
return CLKS_TRUE;
}
static i32 clks_exec_dynlib_alloc_slot(void) {
u32 i;
for (i = 0U; i < CLKS_EXEC_DYNLIB_MAX; i++) {
if (clks_exec_dynlib_table[i].used == CLKS_FALSE) {
return (i32)i;
}
}
return -1;
}
static i32 clks_exec_dynlib_find_by_handle(u64 handle) {
u32 i;
for (i = 0U; i < CLKS_EXEC_DYNLIB_MAX; i++) {
if (clks_exec_dynlib_table[i].used == CLKS_TRUE && clks_exec_dynlib_table[i].handle == handle) {
return (i32)i;
}
}
return -1;
}
static i32 clks_exec_dynlib_find_by_owner_path(u64 owner_pid, const char *path) {
u32 i;
if (path == CLKS_NULL) {
return -1;
}
for (i = 0U; i < CLKS_EXEC_DYNLIB_MAX; i++) {
if (clks_exec_dynlib_table[i].used != CLKS_TRUE) {
continue;
}
if (clks_exec_dynlib_table[i].owner_pid == owner_pid &&
clks_strcmp(clks_exec_dynlib_table[i].path, path) == 0) {
return (i32)i;
}
}
return -1;
}
static u64 clks_exec_dynlib_alloc_handle(void) {
u64 handle = clks_exec_next_dynlib_handle;
clks_exec_next_dynlib_handle++;
if (clks_exec_next_dynlib_handle == 0ULL) {
clks_exec_next_dynlib_handle = 1ULL;
}
if (handle == 0ULL) {
handle = clks_exec_next_dynlib_handle;
clks_exec_next_dynlib_handle++;
if (clks_exec_next_dynlib_handle == 0ULL) {
clks_exec_next_dynlib_handle = 1ULL;
}
}
return handle;
}
static void clks_exec_dynlib_slot_reset(struct clks_exec_dynlib_slot *slot) {
if (slot == CLKS_NULL) {
return;
}
if (slot->used == CLKS_TRUE && slot->loaded.image_base != CLKS_NULL) {
clks_elf64_unload(&slot->loaded);
}
clks_memset(slot, 0, sizeof(*slot));
}
static void clks_exec_dynlib_release_owner(u64 owner_pid) {
u32 i;
if (owner_pid == 0ULL) {
return;
}
for (i = 0U; i < CLKS_EXEC_DYNLIB_MAX; i++) {
if (clks_exec_dynlib_table[i].used == CLKS_TRUE &&
clks_exec_dynlib_table[i].owner_pid == owner_pid) {
clks_exec_dynlib_slot_reset(&clks_exec_dynlib_table[i]);
}
}
}
static clks_bool clks_exec_dynlib_elf_header_ok(const struct clks_exec_elf64_ehdr *eh) {
if (eh == CLKS_NULL) {
return CLKS_FALSE;
}
if (eh->e_ident[0] != CLKS_EXEC_ELF64_MAGIC_0 ||
eh->e_ident[1] != CLKS_EXEC_ELF64_MAGIC_1 ||
eh->e_ident[2] != CLKS_EXEC_ELF64_MAGIC_2 ||
eh->e_ident[3] != CLKS_EXEC_ELF64_MAGIC_3) {
return CLKS_FALSE;
}
if (eh->e_ident[4] != CLKS_EXEC_ELF64_CLASS_64 || eh->e_ident[5] != CLKS_EXEC_ELF64_DATA_LSB) {
return CLKS_FALSE;
}
if (eh->e_ident[6] != CLKS_EXEC_ELF64_VERSION || eh->e_version != CLKS_EXEC_ELF64_VERSION) {
return CLKS_FALSE;
}
if (eh->e_shentsize != sizeof(struct clks_exec_elf64_shdr)) {
return CLKS_FALSE;
}
return CLKS_TRUE;
}
static clks_bool clks_exec_dynlib_symbol_name_ptr(const char *strtab,
u64 strtab_size,
u32 st_name,
const char **out_name) {
u64 i;
if (out_name != CLKS_NULL) {
*out_name = CLKS_NULL;
}
if (strtab == CLKS_NULL || out_name == CLKS_NULL || st_name >= strtab_size) {
return CLKS_FALSE;
}
for (i = (u64)st_name; i < strtab_size; i++) {
if (strtab[i] == '\0') {
*out_name = &strtab[st_name];
return CLKS_TRUE;
}
}
return CLKS_FALSE;
}
static clks_bool clks_exec_dynlib_resolve_symbol(const struct clks_exec_dynlib_slot *slot,
const char *symbol,
u64 *out_addr) {
const struct clks_exec_elf64_ehdr *eh;
const struct clks_exec_elf64_shdr *shdrs;
const u8 *image;
u64 i;
u64 sh_table_size;
if (out_addr != CLKS_NULL) {
*out_addr = 0ULL;
}
if (slot == CLKS_NULL || slot->used != CLKS_TRUE || symbol == CLKS_NULL || symbol[0] == '\0' ||
out_addr == CLKS_NULL) {
return CLKS_FALSE;
}
image = (const u8 *)slot->file_image;
if (image == CLKS_NULL || slot->file_size < sizeof(struct clks_exec_elf64_ehdr)) {
return CLKS_FALSE;
}
eh = (const struct clks_exec_elf64_ehdr *)image;
if (clks_exec_dynlib_elf_header_ok(eh) == CLKS_FALSE || eh->e_shnum == 0U || eh->e_shoff == 0ULL) {
return CLKS_FALSE;
}
sh_table_size = (u64)eh->e_shnum * (u64)eh->e_shentsize;
if (clks_exec_range_ok(eh->e_shoff, sh_table_size, slot->file_size) == CLKS_FALSE) {
return CLKS_FALSE;
}
shdrs = (const struct clks_exec_elf64_shdr *)(image + (usize)eh->e_shoff);
for (i = 0ULL; i < (u64)eh->e_shnum; i++) {
const struct clks_exec_elf64_shdr *symtab = &shdrs[i];
const struct clks_exec_elf64_shdr *strtab;
const struct clks_exec_elf64_sym *symbols;
const char *strings;
u64 sym_count;
u64 j;
if (symtab->sh_type != CLKS_EXEC_ELF64_SHT_SYMTAB && symtab->sh_type != CLKS_EXEC_ELF64_SHT_DYNSYM) {
continue;
}
if (symtab->sh_entsize != sizeof(struct clks_exec_elf64_sym) || symtab->sh_link >= eh->e_shnum ||
symtab->sh_size < symtab->sh_entsize) {
continue;
}
if (clks_exec_range_ok(symtab->sh_offset, symtab->sh_size, slot->file_size) == CLKS_FALSE) {
continue;
}
strtab = &shdrs[symtab->sh_link];
if (clks_exec_range_ok(strtab->sh_offset, strtab->sh_size, slot->file_size) == CLKS_FALSE) {
continue;
}
symbols = (const struct clks_exec_elf64_sym *)(image + (usize)symtab->sh_offset);
strings = (const char *)(image + (usize)strtab->sh_offset);
sym_count = symtab->sh_size / symtab->sh_entsize;
for (j = 0ULL; j < sym_count; j++) {
const struct clks_exec_elf64_sym *sym = &symbols[j];
const char *name_ptr;
u8 symbol_type;
u64 offset;
if (sym->st_name == 0U || sym->st_shndx == CLKS_EXEC_ELF64_SHN_UNDEF || sym->st_value == 0ULL) {
continue;
}
symbol_type = (u8)(sym->st_info & 0x0FU);
if (symbol_type != CLKS_EXEC_ELF64_STT_FUNC && symbol_type != CLKS_EXEC_ELF64_STT_NOTYPE) {
continue;
}
if (clks_exec_dynlib_symbol_name_ptr(strings, strtab->sh_size, sym->st_name, &name_ptr) == CLKS_FALSE) {
continue;
}
if (clks_strcmp(name_ptr, symbol) != 0) {
continue;
}
if (sym->st_value < slot->loaded.image_vaddr_base) {
continue;
}
offset = sym->st_value - slot->loaded.image_vaddr_base;
if (offset >= slot->loaded.image_size) {
continue;
}
*out_addr = (u64)((u8 *)slot->loaded.image_base + (usize)offset);
return CLKS_TRUE;
}
}
return CLKS_FALSE;
}
static void clks_exec_clear_items(char items[][CLKS_EXEC_ITEM_MAX], u32 max_count) { static void clks_exec_clear_items(char items[][CLKS_EXEC_ITEM_MAX], u32 max_count) {
u32 i; u32 i;
@@ -931,6 +1259,8 @@ static clks_bool clks_exec_run_proc_slot(i32 slot, u64 *out_status) {
clks_exec_proc_mark_exited(proc, clks_interrupts_timer_ticks(), run_ret); clks_exec_proc_mark_exited(proc, clks_interrupts_timer_ticks(), run_ret);
} }
clks_exec_dynlib_release_owner(proc->pid);
if (depth_pushed == CLKS_TRUE && clks_exec_pid_stack_depth > 0U) { if (depth_pushed == CLKS_TRUE && clks_exec_pid_stack_depth > 0U) {
clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE; clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE;
clks_exec_image_begin_stack[(u32)depth_index] = 0ULL; clks_exec_image_begin_stack[(u32)depth_index] = 0ULL;
@@ -955,6 +1285,7 @@ fail:
} }
clks_exec_proc_mark_exited(proc, clks_interrupts_timer_ticks(), (u64)-1); clks_exec_proc_mark_exited(proc, clks_interrupts_timer_ticks(), (u64)-1);
clks_exec_dynlib_release_owner(proc->pid);
if (depth_pushed == CLKS_TRUE && clks_exec_pid_stack_depth > 0U) { if (depth_pushed == CLKS_TRUE && clks_exec_pid_stack_depth > 0U) {
clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE; clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE;
@@ -1066,6 +1397,8 @@ void clks_exec_init(void) {
clks_memset(clks_exec_image_begin_stack, 0, sizeof(clks_exec_image_begin_stack)); clks_memset(clks_exec_image_begin_stack, 0, sizeof(clks_exec_image_begin_stack));
clks_memset(clks_exec_image_end_stack, 0, sizeof(clks_exec_image_end_stack)); clks_memset(clks_exec_image_end_stack, 0, sizeof(clks_exec_image_end_stack));
clks_memset(clks_exec_proc_table, 0, sizeof(clks_exec_proc_table)); clks_memset(clks_exec_proc_table, 0, sizeof(clks_exec_proc_table));
clks_memset(clks_exec_dynlib_table, 0, sizeof(clks_exec_dynlib_table));
clks_exec_next_dynlib_handle = 1ULL;
clks_exec_log_info_serial("PATH EXEC FRAMEWORK ONLINE"); clks_exec_log_info_serial("PATH EXEC FRAMEWORK ONLINE");
} }
@@ -1324,13 +1657,7 @@ u64 clks_exec_fd_write(u64 fd, const void *buffer, u64 size) {
} }
if (entry->kind == CLKS_EXEC_FD_KIND_TTY) { if (entry->kind == CLKS_EXEC_FD_KIND_TTY) {
u64 i; clks_tty_write_n((const char *)buffer, (usize)size);
const char *src = (const char *)buffer;
for (i = 0ULL; i < size; i++) {
clks_tty_write_char(src[i]);
}
return size; return size;
} }
@@ -1384,6 +1711,119 @@ u64 clks_exec_fd_dup(u64 fd) {
return (u64)fd_slot; return (u64)fd_slot;
} }
u64 clks_exec_dl_open(const char *path) {
struct clks_exec_proc_record *proc = clks_exec_current_proc();
const void *image;
u64 image_size = 0ULL;
i32 existing_slot;
i32 slot;
u64 owner_pid;
struct clks_exec_dynlib_slot *dyn;
if (proc == CLKS_NULL || path == CLKS_NULL || path[0] != '/') {
return (u64)-1;
}
if (clks_strlen(path) >= CLKS_EXEC_PATH_MAX) {
return (u64)-1;
}
owner_pid = proc->pid;
existing_slot = clks_exec_dynlib_find_by_owner_path(owner_pid, path);
if (existing_slot >= 0) {
dyn = &clks_exec_dynlib_table[(u32)existing_slot];
dyn->ref_count++;
return dyn->handle;
}
slot = clks_exec_dynlib_alloc_slot();
if (slot < 0) {
return (u64)-1;
}
image = clks_fs_read_all(path, &image_size);
if (image == CLKS_NULL || image_size == 0ULL) {
return (u64)-1;
}
dyn = &clks_exec_dynlib_table[(u32)slot];
clks_memset(dyn, 0, sizeof(*dyn));
if (clks_elf64_load(image, image_size, &dyn->loaded) == CLKS_FALSE) {
clks_memset(dyn, 0, sizeof(*dyn));
return (u64)-1;
}
dyn->used = CLKS_TRUE;
dyn->handle = clks_exec_dynlib_alloc_handle();
dyn->owner_pid = owner_pid;
dyn->ref_count = 1ULL;
dyn->file_image = image;
dyn->file_size = image_size;
clks_exec_copy_path(dyn->path, sizeof(dyn->path), path);
clks_exec_log_info_serial("DLOPEN OK");
clks_exec_log_info_serial(path);
clks_exec_log_hex_serial("DL_HANDLE", dyn->handle);
return dyn->handle;
}
u64 clks_exec_dl_close(u64 handle) {
struct clks_exec_proc_record *proc = clks_exec_current_proc();
i32 slot;
struct clks_exec_dynlib_slot *dyn;
if (proc == CLKS_NULL || handle == 0ULL) {
return (u64)-1;
}
slot = clks_exec_dynlib_find_by_handle(handle);
if (slot < 0) {
return (u64)-1;
}
dyn = &clks_exec_dynlib_table[(u32)slot];
if (dyn->owner_pid != proc->pid) {
return (u64)-1;
}
if (dyn->ref_count > 1ULL) {
dyn->ref_count--;
return 0ULL;
}
clks_exec_dynlib_slot_reset(dyn);
return 0ULL;
}
u64 clks_exec_dl_sym(u64 handle, const char *symbol) {
struct clks_exec_proc_record *proc = clks_exec_current_proc();
i32 slot;
struct clks_exec_dynlib_slot *dyn;
u64 addr = 0ULL;
if (proc == CLKS_NULL || handle == 0ULL || symbol == CLKS_NULL || symbol[0] == '\0') {
return 0ULL;
}
slot = clks_exec_dynlib_find_by_handle(handle);
if (slot < 0) {
return 0ULL;
}
dyn = &clks_exec_dynlib_table[(u32)slot];
if (dyn->owner_pid != proc->pid) {
return 0ULL;
}
if (clks_exec_dynlib_resolve_symbol(dyn, symbol, &addr) == CLKS_FALSE) {
return 0ULL;
}
return addr;
}
u64 clks_exec_current_pid(void) { u64 clks_exec_current_pid(void) {
i32 depth_index = clks_exec_current_depth_index(); i32 depth_index = clks_exec_current_depth_index();

View File

@@ -32,7 +32,7 @@
#define CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES (128ULL * 1024ULL) #define CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES (128ULL * 1024ULL)
#define CLKS_SYSCALL_KERNEL_SYMBOL_FILE "/system/kernel.sym" #define CLKS_SYSCALL_KERNEL_SYMBOL_FILE "/system/kernel.sym"
#define CLKS_SYSCALL_KERNEL_ADDR_BASE 0xFFFF800000000000ULL #define CLKS_SYSCALL_KERNEL_ADDR_BASE 0xFFFF800000000000ULL
#define CLKS_SYSCALL_STATS_MAX_ID CLKS_SYSCALL_FD_DUP #define CLKS_SYSCALL_STATS_MAX_ID CLKS_SYSCALL_DL_SYM
#define CLKS_SYSCALL_STATS_RING_SIZE 256U #define CLKS_SYSCALL_STATS_RING_SIZE 256U
struct clks_syscall_frame { struct clks_syscall_frame {
@@ -244,6 +244,30 @@ static u64 clks_syscall_fd_dup(u64 arg0) {
return clks_exec_fd_dup(arg0); return clks_exec_fd_dup(arg0);
} }
static u64 clks_syscall_dl_open(u64 arg0) {
char path[CLKS_SYSCALL_PATH_MAX];
if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) {
return (u64)-1;
}
return clks_exec_dl_open(path);
}
static u64 clks_syscall_dl_close(u64 arg0) {
return clks_exec_dl_close(arg0);
}
static u64 clks_syscall_dl_sym(u64 arg0, u64 arg1) {
char symbol[CLKS_SYSCALL_NAME_MAX];
if (clks_syscall_copy_user_string(arg1, symbol, sizeof(symbol)) == CLKS_FALSE) {
return 0ULL;
}
return clks_exec_dl_sym(arg0, symbol);
}
static clks_bool clks_syscall_procfs_is_root(const char *path) { static clks_bool clks_syscall_procfs_is_root(const char *path) {
return (path != CLKS_NULL && clks_strcmp(path, "/proc") == 0) ? CLKS_TRUE : CLKS_FALSE; return (path != CLKS_NULL && clks_strcmp(path, "/proc") == 0) ? CLKS_TRUE : CLKS_FALSE;
} }
@@ -1830,6 +1854,12 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
return clks_syscall_fd_close(frame->rbx); return clks_syscall_fd_close(frame->rbx);
case CLKS_SYSCALL_FD_DUP: case CLKS_SYSCALL_FD_DUP:
return clks_syscall_fd_dup(frame->rbx); return clks_syscall_fd_dup(frame->rbx);
case CLKS_SYSCALL_DL_OPEN:
return clks_syscall_dl_open(frame->rbx);
case CLKS_SYSCALL_DL_CLOSE:
return clks_syscall_dl_close(frame->rbx);
case CLKS_SYSCALL_DL_SYM:
return clks_syscall_dl_sym(frame->rbx, frame->rcx);
default: default:
return (u64)-1; return (u64)-1;
} }

View File

@@ -1215,11 +1215,11 @@ void clks_tty_write_char(char ch) {
clks_tty_reset_blink_timer(); clks_tty_reset_blink_timer();
} }
void clks_tty_write(const char *text) { void clks_tty_write_n(const char *text, usize len) {
usize i = 0U; usize i = 0U;
u32 tty_index; u32 tty_index;
if (clks_tty_is_ready == CLKS_FALSE || text == CLKS_NULL) { if (clks_tty_is_ready == CLKS_FALSE || text == CLKS_NULL || len == 0U) {
return; return;
} }
@@ -1231,7 +1231,7 @@ void clks_tty_write(const char *text) {
clks_tty_redraw_active(); clks_tty_redraw_active();
} }
while (text[i] != '\0') { while (i < len) {
if (clks_tty_ansi_process_byte(tty_index, text[i]) == CLKS_FALSE) { if (clks_tty_ansi_process_byte(tty_index, text[i]) == CLKS_FALSE) {
clks_tty_put_char_raw(tty_index, text[i]); clks_tty_put_char_raw(tty_index, text[i]);
} }
@@ -1244,6 +1244,14 @@ void clks_tty_write(const char *text) {
clks_tty_reset_blink_timer(); clks_tty_reset_blink_timer();
} }
void clks_tty_write(const char *text) {
if (text == CLKS_NULL) {
return;
}
clks_tty_write_n(text, clks_strlen(text));
}
void clks_tty_switch(u32 tty_index) { void clks_tty_switch(u32 tty_index) {
if (clks_tty_is_ready == CLKS_FALSE) { if (clks_tty_is_ready == CLKS_FALSE) {
return; return;