更好的Panic、

This commit is contained in:
2026-04-17 18:26:39 +08:00
parent cb2406cbed
commit bf6720c6e8
6 changed files with 502 additions and 11 deletions

View File

@@ -11,6 +11,7 @@ set(LD "x86_64-elf-ld" CACHE STRING "Kernel linker")
set(USER_CC "cc" CACHE STRING "User-space C compiler") set(USER_CC "cc" CACHE STRING "User-space C compiler")
set(USER_LD "ld" CACHE STRING "User-space linker") set(USER_LD "ld" CACHE STRING "User-space linker")
set(RUSTC "rustc" CACHE STRING "Rust compiler") set(RUSTC "rustc" CACHE STRING "Rust compiler")
set(NM "nm" CACHE STRING "nm executable")
set(XORRISO "xorriso" CACHE STRING "xorriso executable") set(XORRISO "xorriso" CACHE STRING "xorriso executable")
set(TAR "tar" CACHE STRING "tar executable") set(TAR "tar" CACHE STRING "tar executable")
@@ -87,6 +88,7 @@ set(RAMDISK_ROOT "${BUILD_ROOT}/ramdisk_root")
set(KERNEL_ELF "${BUILD_ROOT}/clks_kernel.elf") set(KERNEL_ELF "${BUILD_ROOT}/clks_kernel.elf")
set(RAMDISK_IMAGE "${BUILD_ROOT}/cleonos_ramdisk.tar") set(RAMDISK_IMAGE "${BUILD_ROOT}/cleonos_ramdisk.tar")
set(ISO_IMAGE "${CMAKE_SOURCE_DIR}/build/CLeonOS-x86_64.iso") set(ISO_IMAGE "${CMAKE_SOURCE_DIR}/build/CLeonOS-x86_64.iso")
set(KERNEL_SYMBOLS_FILE "${BUILD_ROOT}/kernel.sym")
set(USER_BUILD_ROOT "${BUILD_ROOT}/user") set(USER_BUILD_ROOT "${BUILD_ROOT}/user")
set(USER_OBJ_ROOT "${USER_BUILD_ROOT}/obj") set(USER_OBJ_ROOT "${USER_BUILD_ROOT}/obj")
@@ -99,6 +101,7 @@ resolve_tool_with_fallback(CC gcc cc clang)
resolve_tool_with_fallback(LD ld.lld ld) resolve_tool_with_fallback(LD ld.lld ld)
resolve_tool_with_fallback(USER_CC cc gcc clang) resolve_tool_with_fallback(USER_CC cc gcc clang)
resolve_tool_with_fallback(USER_LD ld.lld ld) resolve_tool_with_fallback(USER_LD ld.lld ld)
resolve_tool_with_fallback(NM llvm-nm x86_64-elf-nm nm)
resolve_tool_with_fallback(OBJCOPY_FOR_TARGET llvm-objcopy x86_64-linux-gnu-objcopy objcopy) resolve_tool_with_fallback(OBJCOPY_FOR_TARGET llvm-objcopy x86_64-linux-gnu-objcopy objcopy)
resolve_tool_with_fallback(OBJDUMP_FOR_TARGET llvm-objdump x86_64-linux-gnu-objdump objdump) resolve_tool_with_fallback(OBJDUMP_FOR_TARGET llvm-objdump x86_64-linux-gnu-objdump objdump)
resolve_tool_with_fallback(READELF_FOR_TARGET llvm-readelf x86_64-linux-gnu-readelf readelf) resolve_tool_with_fallback(READELF_FOR_TARGET llvm-readelf x86_64-linux-gnu-readelf readelf)
@@ -331,6 +334,21 @@ add_custom_command(
add_custom_target(kernel DEPENDS "${KERNEL_ELF}") add_custom_target(kernel DEPENDS "${KERNEL_ELF}")
add_custom_command(
OUTPUT "${KERNEL_SYMBOLS_FILE}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${BUILD_ROOT}"
COMMAND ${CMAKE_COMMAND}
"-DNM_TOOL=${NM}"
"-DKERNEL_ELF=${KERNEL_ELF}"
"-DOUT_SYMBOL_FILE=${KERNEL_SYMBOLS_FILE}"
-P "${CMAKE_SOURCE_DIR}/cmake/gen_kernel_symbols.cmake"
DEPENDS "${KERNEL_ELF}" "${CMAKE_SOURCE_DIR}/cmake/gen_kernel_symbols.cmake"
VERBATIM
)
add_custom_target(kernel-symbols DEPENDS "${KERNEL_SYMBOLS_FILE}")
add_dependencies(kernel-symbols kernel)
set(USER_COMMON_OBJECTS) set(USER_COMMON_OBJECTS)
foreach(SRC IN LISTS USER_COMMON_SOURCES) foreach(SRC IN LISTS USER_COMMON_SOURCES)
add_user_c_object("${SRC}" OBJ_OUT) add_user_c_object("${SRC}" OBJ_OUT)
@@ -496,9 +514,10 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E make_directory "${RAMDISK_ROOT}" COMMAND ${CMAKE_COMMAND} -E make_directory "${RAMDISK_ROOT}"
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/ramdisk" "${RAMDISK_ROOT}" COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/ramdisk" "${RAMDISK_ROOT}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${RAMDISK_ROOT}/system" "${RAMDISK_ROOT}/shell" "${RAMDISK_ROOT}/driver" COMMAND ${CMAKE_COMMAND} -E make_directory "${RAMDISK_ROOT}/system" "${RAMDISK_ROOT}/shell" "${RAMDISK_ROOT}/driver"
COMMAND ${CMAKE_COMMAND} -E copy "${KERNEL_SYMBOLS_FILE}" "${RAMDISK_ROOT}/system/kernel.sym"
${RAMDISK_COPY_COMMANDS} ${RAMDISK_COPY_COMMANDS}
COMMAND ${CMAKE_COMMAND} -E touch "${RAMDISK_ROOT_STAMP}" COMMAND ${CMAKE_COMMAND} -E touch "${RAMDISK_ROOT_STAMP}"
DEPENDS ${RAMDISK_FILES} ${USER_APP_OUTPUTS} DEPENDS ${RAMDISK_FILES} ${USER_APP_OUTPUTS} "${KERNEL_SYMBOLS_FILE}"
VERBATIM VERBATIM
) )
@@ -526,6 +545,7 @@ add_custom_target(setup-tools
"-DOBJCOPY_TOOL=${OBJCOPY_FOR_TARGET}" "-DOBJCOPY_TOOL=${OBJCOPY_FOR_TARGET}"
"-DOBJDUMP_TOOL=${OBJDUMP_FOR_TARGET}" "-DOBJDUMP_TOOL=${OBJDUMP_FOR_TARGET}"
"-DREADELF_TOOL=${READELF_FOR_TARGET}" "-DREADELF_TOOL=${READELF_FOR_TARGET}"
"-DNM_TOOL=${NM}"
"-DUSER_CC_TOOL=${USER_CC}" "-DUSER_CC_TOOL=${USER_CC}"
"-DUSER_LD_TOOL=${USER_LD}" "-DUSER_LD_TOOL=${USER_LD}"
"-DRUSTC_TOOL=${RUSTC}" "-DRUSTC_TOOL=${RUSTC}"

View File

@@ -5,6 +5,11 @@
#include <clks/types.h> #include <clks/types.h>
CLKS_NORETURN void clks_panic(const char *reason); CLKS_NORETURN void clks_panic(const char *reason);
CLKS_NORETURN void clks_panic_exception(const char *name, u64 vector, u64 error_code, u64 rip); CLKS_NORETURN void clks_panic_exception(const char *name,
u64 vector,
u64 error_code,
u64 rip,
u64 rbp,
u64 rsp);
#endif #endif

View File

@@ -260,7 +260,12 @@ void clks_interrupt_dispatch(struct clks_interrupt_frame *frame) {
return; return;
} }
clks_panic_exception(clks_exception_names[vector], vector, frame->error_code, frame->rip); clks_panic_exception(clks_exception_names[vector],
vector,
frame->error_code,
frame->rip,
frame->rbp,
frame->rsp);
} }
if (vector == CLKS_IRQ_TIMER) { if (vector == CLKS_IRQ_TIMER) {

View File

@@ -1,5 +1,6 @@
#include <clks/cpu.h> #include <clks/cpu.h>
#include <clks/framebuffer.h> #include <clks/framebuffer.h>
#include <clks/fs.h>
#include <clks/panic.h> #include <clks/panic.h>
#include <clks/serial.h> #include <clks/serial.h>
#include <clks/string.h> #include <clks/string.h>
@@ -8,6 +9,11 @@
#define CLKS_PANIC_BG 0x00200000U #define CLKS_PANIC_BG 0x00200000U
#define CLKS_PANIC_FG 0x00FFE0E0U #define CLKS_PANIC_FG 0x00FFE0E0U
#define CLKS_PANIC_BACKTRACE_MAX 20U
#define CLKS_PANIC_STACK_WINDOW_BYTES (128ULL * 1024ULL)
#define CLKS_PANIC_SYMBOL_FILE "/system/kernel.sym"
#define CLKS_PANIC_KERNEL_ADDR_BASE 0xFFFF800000000000ULL
struct clks_panic_console { struct clks_panic_console {
u32 cols; u32 cols;
u32 rows; u32 rows;
@@ -18,6 +24,9 @@ struct clks_panic_console {
}; };
static clks_bool clks_panic_active = CLKS_FALSE; static clks_bool clks_panic_active = CLKS_FALSE;
static clks_bool clks_panic_symbols_checked = CLKS_FALSE;
static const char *clks_panic_symbols_data = CLKS_NULL;
static u64 clks_panic_symbols_size = 0ULL;
static inline void clks_panic_disable_interrupts(void) { static inline void clks_panic_disable_interrupts(void) {
#if defined(CLKS_ARCH_X86_64) #if defined(CLKS_ARCH_X86_64)
@@ -41,6 +50,41 @@ static void clks_panic_u64_to_hex(u64 value, char out[19]) {
out[18] = '\0'; out[18] = '\0';
} }
static void clks_panic_u32_to_dec(u32 value, char *out, usize out_size) {
char tmp[11];
usize len = 0U;
usize i;
if (out == CLKS_NULL || out_size == 0U) {
return;
}
if (value == 0U) {
if (out_size >= 2U) {
out[0] = '0';
out[1] = '\0';
} else {
out[0] = '\0';
}
return;
}
while (value != 0U && len < sizeof(tmp)) {
tmp[len++] = (char)('0' + (value % 10U));
value /= 10U;
}
if (len + 1U > out_size) {
len = out_size - 1U;
}
for (i = 0U; i < len; i++) {
out[i] = tmp[len - 1U - i];
}
out[len] = '\0';
}
static clks_bool clks_panic_console_init(struct clks_panic_console *console) { static clks_bool clks_panic_console_init(struct clks_panic_console *console) {
struct clks_framebuffer_info info; struct clks_framebuffer_info info;
@@ -118,19 +162,40 @@ static void clks_panic_console_put_char(struct clks_panic_console *console, char
} }
} }
static void clks_panic_console_write(struct clks_panic_console *console, const char *text) { static void clks_panic_console_write_n(struct clks_panic_console *console, const char *text, usize len) {
usize i = 0U; usize i = 0U;
if (console == CLKS_NULL || text == CLKS_NULL) { if (console == CLKS_NULL || text == CLKS_NULL) {
return; return;
} }
while (text[i] != '\0') { while (i < len) {
clks_panic_console_put_char(console, text[i]); clks_panic_console_put_char(console, text[i]);
i++; i++;
} }
} }
static void clks_panic_console_write(struct clks_panic_console *console, const char *text) {
if (console == CLKS_NULL || text == CLKS_NULL) {
return;
}
clks_panic_console_write_n(console, text, clks_strlen(text));
}
static void clks_panic_serial_write_n(const char *text, usize len) {
usize i = 0U;
if (text == CLKS_NULL) {
return;
}
while (i < len) {
clks_serial_write_char(text[i]);
i++;
}
}
static void clks_panic_serial_write_line(const char *line) { static void clks_panic_serial_write_line(const char *line) {
if (line == CLKS_NULL) { if (line == CLKS_NULL) {
return; return;
@@ -140,12 +205,343 @@ static void clks_panic_serial_write_line(const char *line) {
clks_serial_write("\n"); clks_serial_write("\n");
} }
static clks_bool clks_panic_is_hex(char ch) {
if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
return CLKS_TRUE;
}
return CLKS_FALSE;
}
static u8 clks_panic_hex_value(char ch) {
if (ch >= '0' && ch <= '9') {
return (u8)(ch - '0');
}
if (ch >= 'a' && ch <= 'f') {
return (u8)(10 + (ch - 'a'));
}
return (u8)(10 + (ch - 'A'));
}
static clks_bool clks_panic_parse_symbol_line(const char *line,
usize len,
u64 *out_addr,
const char **out_name,
usize *out_name_len) {
usize i = 0U;
u64 addr = 0ULL;
u32 digits = 0U;
usize name_start;
usize name_end;
if (line == CLKS_NULL || out_addr == CLKS_NULL || out_name == CLKS_NULL || out_name_len == CLKS_NULL) {
return CLKS_FALSE;
}
if (len == 0U) {
return CLKS_FALSE;
}
if (len >= 2U && line[0] == '0' && (line[1] == 'X' || line[1] == 'x')) {
i = 2U;
}
while (i < len && clks_panic_is_hex(line[i]) == CLKS_TRUE) {
addr = (addr << 4) | (u64)clks_panic_hex_value(line[i]);
digits++;
i++;
}
if (digits == 0U) {
return CLKS_FALSE;
}
while (i < len && (line[i] == ' ' || line[i] == '\t')) {
i++;
}
if (i >= len) {
return CLKS_FALSE;
}
name_start = i;
name_end = len;
while (name_end > name_start &&
(line[name_end - 1U] == ' ' || line[name_end - 1U] == '\t' || line[name_end - 1U] == '\r')) {
name_end--;
}
if (name_end <= name_start) {
return CLKS_FALSE;
}
*out_addr = addr;
*out_name = &line[name_start];
*out_name_len = name_end - name_start;
return CLKS_TRUE;
}
static clks_bool clks_panic_symbols_ready(void) {
u64 size = 0ULL;
const void *data;
if (clks_panic_symbols_checked == CLKS_TRUE) {
return (clks_panic_symbols_data != CLKS_NULL && clks_panic_symbols_size > 0ULL) ? CLKS_TRUE : CLKS_FALSE;
}
clks_panic_symbols_checked = CLKS_TRUE;
if (clks_fs_is_ready() == CLKS_FALSE) {
return CLKS_FALSE;
}
data = clks_fs_read_all(CLKS_PANIC_SYMBOL_FILE, &size);
if (data == CLKS_NULL || size == 0ULL) {
return CLKS_FALSE;
}
clks_panic_symbols_data = (const char *)data;
clks_panic_symbols_size = size;
return CLKS_TRUE;
}
static clks_bool clks_panic_lookup_symbol(u64 addr, const char **out_name, usize *out_name_len, u64 *out_base) {
const char *data;
const char *end;
const char *line;
const char *best_name = CLKS_NULL;
usize best_len = 0U;
u64 best_addr = 0ULL;
clks_bool found = CLKS_FALSE;
if (out_name == CLKS_NULL || out_name_len == CLKS_NULL || out_base == CLKS_NULL) {
return CLKS_FALSE;
}
*out_name = CLKS_NULL;
*out_name_len = 0U;
*out_base = 0ULL;
if (clks_panic_symbols_ready() == CLKS_FALSE) {
return CLKS_FALSE;
}
data = clks_panic_symbols_data;
end = clks_panic_symbols_data + clks_panic_symbols_size;
while (data < end) {
u64 line_addr;
const char *line_name;
usize line_name_len;
usize line_len = 0U;
line = data;
while (data < end && *data != '\n') {
data++;
line_len++;
}
if (data < end && *data == '\n') {
data++;
}
if (clks_panic_parse_symbol_line(line, line_len, &line_addr, &line_name, &line_name_len) == CLKS_FALSE) {
continue;
}
if (line_addr <= addr && (found == CLKS_FALSE || line_addr >= best_addr)) {
best_addr = line_addr;
best_name = line_name;
best_len = line_name_len;
found = CLKS_TRUE;
}
}
if (found == CLKS_FALSE) {
return CLKS_FALSE;
}
*out_name = best_name;
*out_name_len = best_len;
*out_base = best_addr;
return CLKS_TRUE;
}
static void clks_panic_emit_bt_entry(struct clks_panic_console *console, u32 index, u64 rip) {
char index_dec[12];
char rip_hex[19];
const char *sym_name = CLKS_NULL;
usize sym_name_len = 0U;
u64 sym_base = 0ULL;
clks_bool has_symbol;
clks_panic_u32_to_dec(index, index_dec, sizeof(index_dec));
clks_panic_u64_to_hex(rip, rip_hex);
has_symbol = clks_panic_lookup_symbol(rip, &sym_name, &sym_name_len, &sym_base);
clks_serial_write("[PANIC][BT] #");
clks_serial_write(index_dec);
clks_serial_write(" ");
clks_serial_write(rip_hex);
if (has_symbol == CLKS_TRUE) {
char off_hex[19];
u64 off = rip - sym_base;
clks_panic_u64_to_hex(off, off_hex);
clks_serial_write(" ");
clks_panic_serial_write_n(sym_name, sym_name_len);
clks_serial_write("+");
clks_serial_write(off_hex);
}
clks_serial_write("\n");
if (console == CLKS_NULL) {
return;
}
clks_panic_console_write(console, "BT#");
clks_panic_console_write(console, index_dec);
clks_panic_console_write(console, " ");
clks_panic_console_write(console, rip_hex);
if (has_symbol == CLKS_TRUE) {
char off_hex[19];
u64 off = rip - sym_base;
clks_panic_u64_to_hex(off, off_hex);
clks_panic_console_write(console, " ");
clks_panic_console_write_n(console, sym_name, sym_name_len);
clks_panic_console_write(console, "+");
clks_panic_console_write(console, off_hex);
}
clks_panic_console_write(console, "\n");
}
static clks_bool clks_panic_stack_ptr_valid(u64 ptr, u64 stack_low, u64 stack_high) {
if ((ptr & 0x7ULL) != 0ULL) {
return CLKS_FALSE;
}
if (ptr < stack_low || ptr + 16ULL > stack_high) {
return CLKS_FALSE;
}
if (ptr < CLKS_PANIC_KERNEL_ADDR_BASE) {
return CLKS_FALSE;
}
return CLKS_TRUE;
}
static void clks_panic_emit_backtrace(struct clks_panic_console *console, u64 rip, u64 rbp, u64 rsp) {
u64 current_rbp;
u64 stack_low;
u64 stack_high;
u32 frame = 0U;
if (rip == 0ULL) {
return;
}
clks_panic_serial_write_line("[PANIC][BT] BEGIN");
if (console != CLKS_NULL) {
clks_panic_console_write(console, "\nBACKTRACE:\n");
}
clks_panic_emit_bt_entry(console, frame, rip);
frame++;
if (rbp == 0ULL || rsp == 0ULL || frame >= CLKS_PANIC_BACKTRACE_MAX) {
clks_panic_serial_write_line("[PANIC][BT] END");
return;
}
stack_low = rsp;
stack_high = rsp + CLKS_PANIC_STACK_WINDOW_BYTES;
if (stack_high <= stack_low) {
clks_panic_serial_write_line("[PANIC][BT] END");
return;
}
current_rbp = rbp;
while (frame < CLKS_PANIC_BACKTRACE_MAX) {
const u64 *frame_ptr;
u64 next_rbp;
u64 ret_rip;
if (clks_panic_stack_ptr_valid(current_rbp, stack_low, stack_high) == CLKS_FALSE) {
break;
}
frame_ptr = (const u64 *)(usize)current_rbp;
next_rbp = frame_ptr[0];
ret_rip = frame_ptr[1];
if (ret_rip == 0ULL) {
break;
}
clks_panic_emit_bt_entry(console, frame, ret_rip);
frame++;
if (next_rbp <= current_rbp) {
break;
}
current_rbp = next_rbp;
}
clks_panic_serial_write_line("[PANIC][BT] END");
}
static void clks_panic_capture_context(u64 *out_rip, u64 *out_rbp, u64 *out_rsp) {
if (out_rip != CLKS_NULL) {
*out_rip = 0ULL;
}
if (out_rbp != CLKS_NULL) {
*out_rbp = 0ULL;
}
if (out_rsp != CLKS_NULL) {
*out_rsp = 0ULL;
}
#if defined(CLKS_ARCH_X86_64)
if (out_rbp != CLKS_NULL) {
__asm__ volatile("mov %%rbp, %0" : "=r"(*out_rbp));
}
if (out_rsp != CLKS_NULL) {
__asm__ volatile("mov %%rsp, %0" : "=r"(*out_rsp));
}
if (out_rip != CLKS_NULL) {
*out_rip = (u64)(usize)__builtin_return_address(0);
}
#endif
}
static CLKS_NORETURN void clks_panic_halt_loop(void) { static CLKS_NORETURN void clks_panic_halt_loop(void) {
clks_cpu_halt_forever(); clks_cpu_halt_forever();
} }
CLKS_NORETURN void clks_panic(const char *reason) { CLKS_NORETURN void clks_panic(const char *reason) {
struct clks_panic_console console; struct clks_panic_console console;
u64 rip = 0ULL;
u64 rbp = 0ULL;
u64 rsp = 0ULL;
clks_panic_disable_interrupts(); clks_panic_disable_interrupts();
@@ -154,6 +550,7 @@ CLKS_NORETURN void clks_panic(const char *reason) {
} }
clks_panic_active = CLKS_TRUE; clks_panic_active = CLKS_TRUE;
clks_panic_capture_context(&rip, &rbp, &rsp);
clks_panic_serial_write_line("[PANIC] CLeonOS KERNEL PANIC"); clks_panic_serial_write_line("[PANIC] CLeonOS KERNEL PANIC");
@@ -173,13 +570,21 @@ CLKS_NORETURN void clks_panic(const char *reason) {
clks_panic_console_write(&console, "\n"); clks_panic_console_write(&console, "\n");
} }
clks_panic_emit_backtrace(&console, rip, rbp, rsp);
clks_panic_console_write(&console, "\nSystem halted. Please reboot the VM.\n"); clks_panic_console_write(&console, "\nSystem halted. Please reboot the VM.\n");
} else {
clks_panic_emit_backtrace(CLKS_NULL, rip, rbp, rsp);
} }
clks_panic_halt_loop(); clks_panic_halt_loop();
} }
CLKS_NORETURN void clks_panic_exception(const char *name, u64 vector, u64 error_code, u64 rip) { CLKS_NORETURN void clks_panic_exception(const char *name,
u64 vector,
u64 error_code,
u64 rip,
u64 rbp,
u64 rsp) {
struct clks_panic_console console; struct clks_panic_console console;
char hex_buf[19]; char hex_buf[19];
@@ -230,10 +635,13 @@ CLKS_NORETURN void clks_panic_exception(const char *name, u64 vector, u64 error_
clks_panic_u64_to_hex(rip, hex_buf); clks_panic_u64_to_hex(rip, hex_buf);
clks_panic_console_write(&console, "RIP: "); clks_panic_console_write(&console, "RIP: ");
clks_panic_console_write(&console, hex_buf); clks_panic_console_write(&console, hex_buf);
clks_panic_console_write(&console, "\n\n"); clks_panic_console_write(&console, "\n");
clks_panic_console_write(&console, "System halted. Please reboot the VM.\n"); clks_panic_emit_backtrace(&console, rip, rbp, rsp);
clks_panic_console_write(&console, "\nSystem halted. Please reboot the VM.\n");
} else {
clks_panic_emit_backtrace(CLKS_NULL, rip, rbp, rsp);
} }
clks_panic_halt_loop(); clks_panic_halt_loop();
} }

View File

@@ -29,10 +29,11 @@ require_tool("${LD_TOOL}")
require_tool("${OBJCOPY_TOOL}") require_tool("${OBJCOPY_TOOL}")
require_tool("${OBJDUMP_TOOL}") require_tool("${OBJDUMP_TOOL}")
require_tool("${READELF_TOOL}") require_tool("${READELF_TOOL}")
require_tool("${NM_TOOL}")
require_tool("${USER_CC_TOOL}") require_tool("${USER_CC_TOOL}")
require_tool("${USER_LD_TOOL}") require_tool("${USER_LD_TOOL}")
require_tool("${RUSTC_TOOL}") require_tool("${RUSTC_TOOL}")
require_tool("${MAKE_TOOL}") require_tool("${MAKE_TOOL}")
require_tool("${SH_TOOL}") require_tool("${SH_TOOL}")
cl_log_info("required tools are available") cl_log_info("required tools are available")

View File

@@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 3.20)
if(NOT DEFINED NM_TOOL OR "${NM_TOOL}" STREQUAL "")
message(FATAL_ERROR "NM_TOOL is required")
endif()
if(NOT DEFINED KERNEL_ELF OR "${KERNEL_ELF}" STREQUAL "")
message(FATAL_ERROR "KERNEL_ELF is required")
endif()
if(NOT DEFINED OUT_SYMBOL_FILE OR "${OUT_SYMBOL_FILE}" STREQUAL "")
message(FATAL_ERROR "OUT_SYMBOL_FILE is required")
endif()
execute_process(
COMMAND "${NM_TOOL}" -n "${KERNEL_ELF}"
RESULT_VARIABLE _nm_result
OUTPUT_VARIABLE _nm_output
ERROR_VARIABLE _nm_error
)
if(NOT _nm_result EQUAL 0)
message(FATAL_ERROR "failed to run nm (${_nm_result}): ${_nm_error}")
endif()
string(REPLACE "\r\n" "\n" _nm_output "${_nm_output}")
string(REPLACE "\r" "\n" _nm_output "${_nm_output}")
string(REPLACE "\n" ";" _nm_lines "${_nm_output}")
set(_out_text "CLEONOS_KERNEL_SYMBOLS_V1\n")
foreach(_line IN LISTS _nm_lines)
string(STRIP "${_line}" _line)
if(_line STREQUAL "")
continue()
endif()
if(_line MATCHES "^([0-9A-Fa-f]+)[ \t]+([tTwW])[ \t]+(.+)$")
set(_addr "${CMAKE_MATCH_1}")
set(_name "${CMAKE_MATCH_3}")
if(_name MATCHES "^\\.")
continue()
endif()
string(TOUPPER "${_addr}" _addr_upper)
set(_out_text "${_out_text}0X${_addr_upper} ${_name}\n")
endif()
endforeach()
file(WRITE "${OUT_SYMBOL_FILE}" "${_out_text}")