From 27a51a0986832d76767c34409d90f28b2a436df9 Mon Sep 17 00:00:00 2001 From: Leonmmcoset Date: Mon, 20 Apr 2026 23:46:16 +0800 Subject: [PATCH] doom3 --- cleonos/c/apps/doom/doom_compat.c | 44 ++++++ cleonos/c/src/stdio.c | 237 ++++++++++++++++++++++++++++-- clks/kernel/runtime/elf64.c | 49 ++++++ clks/kernel/runtime/exec.c | 68 +++++++++ 4 files changed, 387 insertions(+), 11 deletions(-) diff --git a/cleonos/c/apps/doom/doom_compat.c b/cleonos/c/apps/doom/doom_compat.c index 04cc3e4..cc20692 100644 --- a/cleonos/c/apps/doom/doom_compat.c +++ b/cleonos/c/apps/doom/doom_compat.c @@ -18,6 +18,8 @@ #define DG_PATH_MAX 192 #define DG_ENV_LINE_MAX 256 #define DG_STDIO_MAGIC 0x44474D46U +#define DG_SERIAL_LOG_CHUNK 176U +#define DG_SERIAL_LOG_PREFIX "[DOOM] " struct dg_alloc_hdr { size_t size; @@ -385,6 +387,47 @@ static int dg_fd_flush_slot(struct dg_mem_fd *file) { return 0; } +static void dg_serial_log_bytes(const void *buffer, size_t size) { + const unsigned char *src = (const unsigned char *)buffer; + static const char prefix[] = DG_SERIAL_LOG_PREFIX; + char line[DG_SERIAL_LOG_CHUNK + sizeof(prefix) + 1U]; + size_t prefix_len = sizeof(prefix) - 1U; + size_t offset = 0U; + int first = 1; + + if (src == (const unsigned char *)0 || size == 0U) { + return; + } + + while (offset < size) { + size_t room = DG_SERIAL_LOG_CHUNK; + size_t used = 0U; + + if (first != 0 && prefix_len < sizeof(line)) { + memcpy(line, prefix, prefix_len); + used = prefix_len; + first = 0; + } + + while (offset < size && room > 0U) { + unsigned char ch = src[offset++]; + + if (ch == '\0') { + ch = ' '; + } else if (ch < 32U && ch != '\n' && ch != '\r' && ch != '\t') { + ch = ' '; + } + + line[used++] = (char)ch; + room--; + } + + if (used > 0U) { + (void)cleonos_sys_log_write(line, (u64)used); + } + } +} + void *malloc(size_t size) { struct dg_alloc_hdr *cur; size_t aligned; @@ -943,6 +986,7 @@ ssize_t write(int fd, const void *buf, size_t size) { errno = EIO; return -1; } + dg_serial_log_bytes(buf, (size_t)wrote); return (ssize_t)wrote; } diff --git a/cleonos/c/src/stdio.c b/cleonos/c/src/stdio.c index 6ac2e51..016ddcf 100644 --- a/cleonos/c/src/stdio.c +++ b/cleonos/c/src/stdio.c @@ -196,6 +196,42 @@ static clio_size_t clio_i64_to_dec(long long value, char *out, clio_size_t out_s return offset + len; } +static int clio_is_digit(char ch) { + return (ch >= '0' && ch <= '9') ? 1 : 0; +} + +static int clio_emit_repeat(struct clio_sink *sink, char ch, clio_size_t count) { + while (count > 0UL) { + if (clio_sink_emit(sink, &ch, 1UL) == 0) { + return 0; + } + count--; + } + + return 1; +} + +static int clio_emit_with_width(struct clio_sink *sink, const char *text, clio_size_t text_len, int left_align, + char pad_char, clio_size_t width) { + if (left_align == 0 && width > text_len) { + if (clio_emit_repeat(sink, pad_char, width - text_len) == 0) { + return 0; + } + } + + if (text_len > 0UL && clio_sink_emit(sink, text, text_len) == 0) { + return 0; + } + + if (left_align != 0 && width > text_len) { + if (clio_emit_repeat(sink, ' ', width - text_len) == 0) { + return 0; + } + } + + return 1; +} + static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) { const char *cursor = fmt; @@ -223,10 +259,43 @@ static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) { } { + int left_align = 0; + int zero_pad = 0; + clio_size_t width = 0UL; + int has_precision = 0; + clio_size_t precision = 0UL; int length_mode = 0; /* 0: default, 1: l, 2: ll, 3: z */ char spec = *cursor; - char number_buf[64]; - clio_size_t out_len = 0UL; + char number_buf[96]; + + while (spec == '-' || spec == '0') { + if (spec == '-') { + left_align = 1; + } else if (spec == '0') { + zero_pad = 1; + } + cursor++; + spec = *cursor; + } + + while (clio_is_digit(spec) != 0) { + width = (width * 10UL) + (clio_size_t)(unsigned long)(spec - '0'); + cursor++; + spec = *cursor; + } + + if (spec == '.') { + has_precision = 1; + precision = 0UL; + cursor++; + spec = *cursor; + + while (clio_is_digit(spec) != 0) { + precision = (precision * 10UL) + (clio_size_t)(unsigned long)(spec - '0'); + cursor++; + spec = *cursor; + } + } if (spec == 'l') { cursor++; @@ -250,24 +319,36 @@ static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) { if (spec == 's') { const char *text = va_arg(args, const char *); + clio_size_t text_len; if (text == (const char *)0) { text = "(null)"; } - out_len = clio_strlen(text); + text_len = clio_strlen(text); + if (has_precision != 0 && precision < text_len) { + text_len = precision; + } - if (clio_sink_emit(sink, text, out_len) == 0) { + if (clio_emit_with_width(sink, text, text_len, left_align, ' ', width) == 0) { return EOF; } } else if (spec == 'c') { char out = (char)va_arg(args, int); + char out_buf[1]; - if (clio_sink_emit(sink, &out, 1UL) == 0) { + out_buf[0] = out; + if (clio_emit_with_width(sink, out_buf, 1UL, left_align, ' ', width) == 0) { return EOF; } } else if (spec == 'd' || spec == 'i') { long long value; + char sign_char = '\0'; + const char *digits = number_buf; + clio_size_t digits_len; + clio_size_t leading_zeros = 0UL; + clio_size_t core_len; + int sign_emitted = 0; if (length_mode == 2) { value = va_arg(args, long long); @@ -279,14 +360,72 @@ static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) { value = (long long)va_arg(args, int); } - out_len = clio_i64_to_dec(value, number_buf, (clio_size_t)sizeof(number_buf)); - if (out_len == 0UL || clio_sink_emit(sink, number_buf, out_len) == 0) { + digits_len = clio_i64_to_dec(value, number_buf, (clio_size_t)sizeof(number_buf)); + if (digits_len == 0UL) { return EOF; } + + if (number_buf[0] == '-') { + sign_char = '-'; + digits = number_buf + 1; + digits_len--; + } + + if (has_precision != 0 && precision == 0UL && value == 0LL) { + digits_len = 0UL; + } + + if (has_precision != 0 && precision > digits_len) { + leading_zeros = precision - digits_len; + } + + core_len = digits_len + leading_zeros + ((sign_char != '\0') ? 1UL : 0UL); + + if (left_align == 0 && width > core_len) { + if (zero_pad != 0 && has_precision == 0) { + if (sign_char != '\0') { + if (clio_sink_emit(sink, &sign_char, 1UL) == 0) { + return EOF; + } + sign_emitted = 1; + } + if (clio_emit_repeat(sink, '0', width - core_len) == 0) { + return EOF; + } + } else { + if (clio_emit_repeat(sink, ' ', width - core_len) == 0) { + return EOF; + } + } + } + + if (sign_char != '\0' && sign_emitted == 0) { + if (clio_sink_emit(sink, &sign_char, 1UL) == 0) { + return EOF; + } + } + + if (clio_emit_repeat(sink, '0', leading_zeros) == 0) { + return EOF; + } + + if (digits_len > 0UL && clio_sink_emit(sink, digits, digits_len) == 0) { + return EOF; + } + + if (left_align != 0 && width > core_len) { + if (clio_emit_repeat(sink, ' ', width - core_len) == 0) { + return EOF; + } + } } else if (spec == 'u' || spec == 'x' || spec == 'X') { unsigned long long value; unsigned int base = (spec == 'u') ? 10U : 16U; int upper = (spec == 'X') ? 1 : 0; + clio_size_t digits_len; + clio_size_t leading_zeros = 0UL; + clio_size_t core_len; + char pad_char = ' '; if (length_mode == 2) { value = va_arg(args, unsigned long long); @@ -298,22 +437,98 @@ static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) { value = (unsigned long long)va_arg(args, unsigned int); } - out_len = clio_u64_to_base(value, base, upper, number_buf, (clio_size_t)sizeof(number_buf)); - if (out_len == 0UL || clio_sink_emit(sink, number_buf, out_len) == 0) { + digits_len = clio_u64_to_base(value, base, upper, number_buf, (clio_size_t)sizeof(number_buf)); + if (digits_len == 0UL) { return EOF; } + + if (has_precision != 0 && precision == 0UL && value == 0ULL) { + digits_len = 0UL; + } + + if (has_precision != 0 && precision > digits_len) { + leading_zeros = precision - digits_len; + } + + core_len = digits_len + leading_zeros; + + if (zero_pad != 0 && has_precision == 0 && left_align == 0) { + pad_char = '0'; + } + + if (left_align == 0 && width > core_len) { + if (clio_emit_repeat(sink, pad_char, width - core_len) == 0) { + return EOF; + } + } + + if (clio_emit_repeat(sink, '0', leading_zeros) == 0) { + return EOF; + } + + if (digits_len > 0UL && clio_sink_emit(sink, number_buf, digits_len) == 0) { + return EOF; + } + + if (left_align != 0 && width > core_len) { + if (clio_emit_repeat(sink, ' ', width - core_len) == 0) { + return EOF; + } + } } else if (spec == 'p') { const void *ptr = va_arg(args, const void *); unsigned long long value = (unsigned long long)(unsigned long)ptr; + clio_size_t digits_len; + clio_size_t leading_zeros = 0UL; + clio_size_t core_len; + + digits_len = clio_u64_to_base(value, 16U, 0, number_buf, (clio_size_t)sizeof(number_buf)); + if (digits_len == 0UL) { + return EOF; + } + + if (has_precision != 0 && precision == 0UL && value == 0ULL) { + digits_len = 0UL; + } + + if (has_precision != 0 && precision > digits_len) { + leading_zeros = precision - digits_len; + } + + core_len = 2UL + leading_zeros + digits_len; + + if (left_align == 0 && width > core_len) { + if (clio_emit_repeat(sink, ' ', width - core_len) == 0) { + return EOF; + } + } if (clio_sink_emit(sink, "0x", 2UL) == 0) { return EOF; } - out_len = clio_u64_to_base(value, 16U, 0, number_buf, (clio_size_t)sizeof(number_buf)); - if (out_len == 0UL || clio_sink_emit(sink, number_buf, out_len) == 0) { + if (clio_emit_repeat(sink, '0', leading_zeros) == 0) { return EOF; } + + if (digits_len > 0UL && clio_sink_emit(sink, number_buf, digits_len) == 0) { + return EOF; + } + + if (left_align != 0 && width > core_len) { + if (clio_emit_repeat(sink, ' ', width - core_len) == 0) { + return EOF; + } + } + } else if (spec == 'n') { + int *out_count = va_arg(args, int *); + if (out_count != (int *)0) { + if (sink->count > 0x7FFFFFFFUL) { + *out_count = 0x7FFFFFFF; + } else { + *out_count = (int)sink->count; + } + } } else { char fallback[2]; fallback[0] = spec; diff --git a/clks/kernel/runtime/elf64.c b/clks/kernel/runtime/elf64.c index a80c1d3..a52387b 100644 --- a/clks/kernel/runtime/elf64.c +++ b/clks/kernel/runtime/elf64.c @@ -18,6 +18,8 @@ #define CLKS_ELF64_EM_X86_64 62U +#define CLKS_ELF64_PF_X 0x1U + struct clks_elf64_ehdr { u8 e_ident[16]; u16 e_type; @@ -91,6 +93,42 @@ static clks_bool clks_elf64_range_ok(u64 off, u64 len, u64 total) { return CLKS_TRUE; } +static void clks_elf64_rebase_exec_pointers(struct clks_elf64_loaded_image *loaded, u64 old_base, u64 old_end, + u64 delta) { + u16 seg_index; + + if (loaded == CLKS_NULL || delta == 0ULL || old_end <= old_base) { + return; + } + + for (seg_index = 0U; seg_index < loaded->segment_count; seg_index++) { + struct clks_elf64_loaded_segment *seg = &loaded->segments[seg_index]; + u64 scan_len; + u64 off; + + /* Skip executable segments to avoid patching instruction bytes. */ + if ((seg->flags & CLKS_ELF64_PF_X) != 0U) { + continue; + } + + scan_len = seg->filesz; + if (scan_len < sizeof(u64)) { + continue; + } + + scan_len -= (scan_len % sizeof(u64)); + + for (off = 0ULL; off < scan_len; off += sizeof(u64)) { + u64 *slot = (u64 *)((u8 *)seg->base + (usize)off); + u64 value = *slot; + + if (value >= old_base && value < old_end) { + *slot = value + delta; + } + } + } +} + clks_bool clks_elf64_validate(const void *image, u64 size) { const struct clks_elf64_ehdr *eh; u64 ph_table_size; @@ -278,6 +316,17 @@ clks_bool clks_elf64_load(const void *image, u64 size, struct clks_elf64_loaded_ out_loaded->segment_count++; } + if (eh->e_type == CLKS_ELF64_ET_EXEC) { + u64 new_base = (u64)(usize)image_base; + u64 old_base = min_vaddr; + u64 old_end = max_vaddr_end; + + if (new_base != old_base) { + u64 delta = new_base - old_base; + clks_elf64_rebase_exec_pointers(out_loaded, old_base, old_end, delta); + } + } + return CLKS_TRUE; } diff --git a/clks/kernel/runtime/exec.c b/clks/kernel/runtime/exec.c index f0e7283..6c97534 100644 --- a/clks/kernel/runtime/exec.c +++ b/clks/kernel/runtime/exec.c @@ -183,6 +183,8 @@ static u64 clks_exec_unwind_slot_stack[CLKS_EXEC_MAX_DEPTH]; 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_end_stack[CLKS_EXEC_MAX_DEPTH]; +static u64 clks_exec_image_vaddr_begin_stack[CLKS_EXEC_MAX_DEPTH]; +static u64 clks_exec_image_vaddr_end_stack[CLKS_EXEC_MAX_DEPTH]; static u64 clks_exec_stack_begin_stack[CLKS_EXEC_MAX_DEPTH]; static u64 clks_exec_stack_end_stack[CLKS_EXEC_MAX_DEPTH]; static u32 clks_exec_pid_stack_depth = 0U; @@ -322,6 +324,48 @@ static clks_bool clks_exec_rip_is_current_user_context(u64 rip) { return (rip >= image_begin && rip < image_end) ? CLKS_TRUE : CLKS_FALSE; } +static clks_bool clks_exec_translate_legacy_user_rip(u64 rip, u64 *out_rip) { + i32 depth_index; + u64 vaddr_begin; + u64 vaddr_end; + u64 image_begin; + u64 image_end; + u64 off; + u64 translated; + + if (out_rip == CLKS_NULL || clks_exec_pid_stack_depth == 0U) { + return CLKS_FALSE; + } + + depth_index = (i32)(clks_exec_pid_stack_depth - 1U); + vaddr_begin = clks_exec_image_vaddr_begin_stack[(u32)depth_index]; + vaddr_end = clks_exec_image_vaddr_end_stack[(u32)depth_index]; + image_begin = clks_exec_image_begin_stack[(u32)depth_index]; + image_end = clks_exec_image_end_stack[(u32)depth_index]; + + if (vaddr_begin == 0ULL || vaddr_end <= vaddr_begin || image_begin == 0ULL || image_end <= image_begin) { + return CLKS_FALSE; + } + + if (rip < vaddr_begin || rip >= vaddr_end) { + return CLKS_FALSE; + } + + off = rip - vaddr_begin; + + if (off >= (image_end - image_begin)) { + return CLKS_FALSE; + } + + translated = image_begin + off; + if (translated < image_begin || translated >= image_end) { + return CLKS_FALSE; + } + + *out_rip = translated; + return CLKS_TRUE; +} + static void clks_exec_copy_path(char *dst, usize dst_size, const char *src) { usize i = 0U; @@ -1285,6 +1329,8 @@ static clks_bool clks_exec_run_proc_slot(i32 slot, u64 *out_status) { clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE; clks_exec_image_begin_stack[(u32)depth_index] = 0ULL; clks_exec_image_end_stack[(u32)depth_index] = 0ULL; + clks_exec_image_vaddr_begin_stack[(u32)depth_index] = 0ULL; + clks_exec_image_vaddr_end_stack[(u32)depth_index] = 0ULL; clks_exec_stack_begin_stack[(u32)depth_index] = 0ULL; clks_exec_stack_end_stack[(u32)depth_index] = 0ULL; clks_exec_pid_stack_depth++; @@ -1333,6 +1379,8 @@ static clks_bool clks_exec_run_proc_slot(i32 slot, u64 *out_status) { clks_exec_image_begin_stack[(u32)depth_index] = image_begin; clks_exec_image_end_stack[(u32)depth_index] = image_end; + clks_exec_image_vaddr_begin_stack[(u32)depth_index] = loaded.image_vaddr_base; + clks_exec_image_vaddr_end_stack[(u32)depth_index] = loaded.image_vaddr_base + loaded.image_size; } clks_exec_log_info_serial("EXEC RUN START"); @@ -1381,6 +1429,8 @@ static clks_bool clks_exec_run_proc_slot(i32 slot, u64 *out_status) { clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE; clks_exec_image_begin_stack[(u32)depth_index] = 0ULL; clks_exec_image_end_stack[(u32)depth_index] = 0ULL; + clks_exec_image_vaddr_begin_stack[(u32)depth_index] = 0ULL; + clks_exec_image_vaddr_end_stack[(u32)depth_index] = 0ULL; clks_exec_stack_begin_stack[(u32)depth_index] = 0ULL; clks_exec_stack_end_stack[(u32)depth_index] = 0ULL; clks_exec_pid_stack_depth--; @@ -1409,6 +1459,8 @@ fail: clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE; clks_exec_image_begin_stack[(u32)depth_index] = 0ULL; clks_exec_image_end_stack[(u32)depth_index] = 0ULL; + clks_exec_image_vaddr_begin_stack[(u32)depth_index] = 0ULL; + clks_exec_image_vaddr_end_stack[(u32)depth_index] = 0ULL; clks_exec_stack_begin_stack[(u32)depth_index] = 0ULL; clks_exec_stack_end_stack[(u32)depth_index] = 0ULL; clks_exec_pid_stack_depth--; @@ -1521,6 +1573,8 @@ void clks_exec_init(void) { clks_memset(clks_exec_unwind_slot_valid_stack, 0, sizeof(clks_exec_unwind_slot_valid_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_vaddr_begin_stack, 0, sizeof(clks_exec_image_vaddr_begin_stack)); + clks_memset(clks_exec_image_vaddr_end_stack, 0, sizeof(clks_exec_image_vaddr_end_stack)); clks_memset(clks_exec_stack_begin_stack, 0, sizeof(clks_exec_stack_begin_stack)); clks_memset(clks_exec_stack_end_stack, 0, sizeof(clks_exec_stack_end_stack)); clks_memset(clks_exec_proc_table, 0, sizeof(clks_exec_proc_table)); @@ -2458,6 +2512,20 @@ clks_bool clks_exec_handle_exception(u64 vector, u64 error_code, u64 rip, u64 *i return CLKS_FALSE; } +#if defined(CLKS_ARCH_X86_64) + if (vector == 14ULL && (error_code & 0x10ULL) != 0ULL && io_rip != CLKS_NULL) { + u64 translated_rip = 0ULL; + + if (clks_exec_translate_legacy_user_rip(rip, &translated_rip) == CLKS_TRUE) { + *io_rip = translated_rip; + clks_exec_log_info_serial("USER RIP LEGACY REBASE"); + clks_exec_log_hex_serial("RIP_OLD", rip); + clks_exec_log_hex_serial("RIP_NEW", translated_rip); + return CLKS_TRUE; + } + } +#endif + signal = clks_exec_signal_from_vector(vector); status = clks_exec_encode_signal_status(signal, vector, error_code);