更好的panic+kdbg

This commit is contained in:
2026-04-17 19:17:03 +08:00
parent bf6720c6e8
commit 5817722cd3
11 changed files with 935 additions and 13 deletions

View File

@@ -12,6 +12,7 @@ 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(NM "nm" CACHE STRING "nm executable")
set(ADDR2LINE "addr2line" CACHE STRING "addr2line 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")
@@ -102,6 +103,7 @@ 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(NM llvm-nm x86_64-elf-nm nm)
resolve_tool_with_fallback(ADDR2LINE llvm-addr2line x86_64-elf-addr2line addr2line)
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)
@@ -121,6 +123,7 @@ set(CFLAGS_COMMON
-ffreestanding -ffreestanding
-fno-stack-protector -fno-stack-protector
-fno-builtin -fno-builtin
-g
-Wall -Wall
-Wextra -Wextra
-Werror -Werror
@@ -339,6 +342,7 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E make_directory "${BUILD_ROOT}" COMMAND ${CMAKE_COMMAND} -E make_directory "${BUILD_ROOT}"
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNM_TOOL=${NM}" "-DNM_TOOL=${NM}"
"-DADDR2LINE_TOOL=${ADDR2LINE}"
"-DKERNEL_ELF=${KERNEL_ELF}" "-DKERNEL_ELF=${KERNEL_ELF}"
"-DOUT_SYMBOL_FILE=${KERNEL_SYMBOLS_FILE}" "-DOUT_SYMBOL_FILE=${KERNEL_SYMBOLS_FILE}"
-P "${CMAKE_SOURCE_DIR}/cmake/gen_kernel_symbols.cmake" -P "${CMAKE_SOURCE_DIR}/cmake/gen_kernel_symbols.cmake"
@@ -382,7 +386,7 @@ set(USER_SHELL_COMMAND_APPS
help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield
bg fg jobs kill ps top bg fg jobs kill ps top
shutdown restart exit clear ansi ansitest wavplay fastfetch memstat fsstat taskstat userstat shutdown restart exit clear ansi ansitest wavplay fastfetch memstat fsstat taskstat userstat
shstat stats tty dmesg kbdstat mkdir touch write append cp mv rm shstat stats tty dmesg kbdstat mkdir touch write append cp mv rm kdbg
) )
foreach(SRC IN LISTS USER_APP_MAIN_SOURCES) foreach(SRC IN LISTS USER_APP_MAIN_SOURCES)
@@ -546,6 +550,7 @@ add_custom_target(setup-tools
"-DOBJDUMP_TOOL=${OBJDUMP_FOR_TARGET}" "-DOBJDUMP_TOOL=${OBJDUMP_FOR_TARGET}"
"-DREADELF_TOOL=${READELF_FOR_TARGET}" "-DREADELF_TOOL=${READELF_FOR_TARGET}"
"-DNM_TOOL=${NM}" "-DNM_TOOL=${NM}"
"-DADDR2LINE_TOOL=${ADDR2LINE}"
"-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

@@ -31,6 +31,7 @@ static int ush_cmd_help(void) {
ush_writeln(" wait <pid> / fg [pid]"); ush_writeln(" wait <pid> / fg [pid]");
ush_writeln(" kill <pid> [signal]"); ush_writeln(" kill <pid> [signal]");
ush_writeln(" jobs [-a] / ps [-a] [-u] / top [--once] [-n loops] [-d ticks]"); ush_writeln(" jobs [-a] / ps [-a] [-u] / top [--once] [-n loops] [-d ticks]");
ush_writeln(" kdbg sym <addr> / kdbg bt <rbp> <rip> / kdbg regs");
ush_writeln(" sleep <ticks>"); ush_writeln(" sleep <ticks>");
ush_writeln(" spin (busy loop test for Alt+Ctrl+C)"); ush_writeln(" spin (busy loop test for Alt+Ctrl+C)");
ush_writeln(" yield"); ush_writeln(" yield");

269
cleonos/c/apps/kdbg_main.c Normal file
View File

@@ -0,0 +1,269 @@
#include "cmd_runtime.h"
#define USH_KDBG_TEXT_MAX 2048ULL
static int ush_kdbg_is_hex(char ch) {
if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
return 1;
}
return 0;
}
static u64 ush_kdbg_hex_value(char ch) {
if (ch >= '0' && ch <= '9') {
return (u64)(ch - '0');
}
if (ch >= 'a' && ch <= 'f') {
return 10ULL + (u64)(ch - 'a');
}
return 10ULL + (u64)(ch - 'A');
}
static int ush_kdbg_parse_u64(const char *text, u64 *out_value) {
u64 value = 0ULL;
u64 i = 0ULL;
int is_hex = 0;
if (text == (const char *)0 || out_value == (u64 *)0 || text[0] == '\0') {
return 0;
}
if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) {
i = 2ULL;
is_hex = 1;
} else if (text[0] == 'x' || text[0] == 'X') {
i = 1ULL;
is_hex = 1;
}
if (is_hex != 0) {
if (text[i] == '\0') {
return 0;
}
while (text[i] != '\0') {
u64 digit;
if (ush_kdbg_is_hex(text[i]) == 0) {
return 0;
}
digit = ush_kdbg_hex_value(text[i]);
if (value > ((0xFFFFFFFFFFFFFFFFULL - digit) >> 4U)) {
return 0;
}
value = (value << 4U) | digit;
i++;
}
*out_value = value;
return 1;
}
return ush_parse_u64_dec(text, out_value);
}
static int ush_kdbg_next_token(const char **io_cursor, char *out, u64 out_size) {
const char *p;
u64 n = 0ULL;
if (io_cursor == (const char **)0 || out == (char *)0 || out_size == 0ULL) {
return 0;
}
p = *io_cursor;
out[0] = '\0';
if (p == (const char *)0) {
return 0;
}
while (*p != '\0' && ush_is_space(*p) != 0) {
p++;
}
if (*p == '\0') {
*io_cursor = p;
return 0;
}
while (*p != '\0' && ush_is_space(*p) == 0) {
if (n + 1ULL < out_size) {
out[n++] = *p;
}
p++;
}
out[n] = '\0';
*io_cursor = p;
return 1;
}
static int ush_kdbg_has_more_tokens(const char *cursor) {
if (cursor == (const char *)0) {
return 0;
}
while (*cursor != '\0') {
if (ush_is_space(*cursor) == 0) {
return 1;
}
cursor++;
}
return 0;
}
static void ush_kdbg_usage(void) {
ush_writeln("usage:");
ush_writeln(" kdbg sym <addr>");
ush_writeln(" kdbg bt <rbp> <rip>");
ush_writeln(" kdbg regs");
}
static int ush_cmd_kdbg(const char *arg) {
const char *cursor = arg;
char subcmd[USH_CMD_MAX];
char tok0[USH_PATH_MAX];
char tok1[USH_PATH_MAX];
char out[USH_KDBG_TEXT_MAX];
u64 got;
u64 value0;
u64 value1;
if (ush_kdbg_next_token(&cursor, subcmd, (u64)sizeof(subcmd)) == 0) {
ush_kdbg_usage();
return 0;
}
if (ush_streq(subcmd, "sym") != 0) {
if (ush_kdbg_next_token(&cursor, tok0, (u64)sizeof(tok0)) == 0 || ush_kdbg_has_more_tokens(cursor) != 0) {
ush_kdbg_usage();
return 0;
}
if (ush_kdbg_parse_u64(tok0, &value0) == 0) {
ush_writeln("kdbg: invalid addr");
return 0;
}
got = cleonos_sys_kdbg_sym(value0, out, (u64)sizeof(out));
if (got == 0ULL) {
ush_writeln("kdbg: sym failed");
return 0;
}
out[(u64)sizeof(out) - 1ULL] = '\0';
ush_writeln(out);
return 1;
}
if (ush_streq(subcmd, "bt") != 0) {
if (ush_kdbg_next_token(&cursor, tok0, (u64)sizeof(tok0)) == 0 ||
ush_kdbg_next_token(&cursor, tok1, (u64)sizeof(tok1)) == 0 ||
ush_kdbg_has_more_tokens(cursor) != 0) {
ush_kdbg_usage();
return 0;
}
if (ush_kdbg_parse_u64(tok0, &value0) == 0 || ush_kdbg_parse_u64(tok1, &value1) == 0) {
ush_writeln("kdbg: invalid rbp/rip");
return 0;
}
got = cleonos_sys_kdbg_bt(value0, value1, out, (u64)sizeof(out));
if (got == 0ULL) {
ush_writeln("kdbg: bt failed");
return 0;
}
out[(u64)sizeof(out) - 1ULL] = '\0';
ush_write(out);
if (got > (u64)sizeof(out) - 1ULL) {
got = (u64)sizeof(out) - 1ULL;
}
if (got > 0ULL && out[got - 1ULL] != '\n') {
ush_write_char('\n');
}
return 1;
}
if (ush_streq(subcmd, "regs") != 0) {
if (ush_kdbg_has_more_tokens(cursor) != 0) {
ush_kdbg_usage();
return 0;
}
got = cleonos_sys_kdbg_regs(out, (u64)sizeof(out));
if (got == 0ULL) {
ush_writeln("kdbg: regs failed");
return 0;
}
out[(u64)sizeof(out) - 1ULL] = '\0';
ush_write(out);
if (got > (u64)sizeof(out) - 1ULL) {
got = (u64)sizeof(out) - 1ULL;
}
if (got > 0ULL && out[got - 1ULL] != '\n') {
ush_write_char('\n');
}
return 1;
}
ush_kdbg_usage();
return 0;
}
int cleonos_app_main(void) {
ush_cmd_ctx ctx;
ush_cmd_ret ret;
ush_state sh;
char initial_cwd[USH_PATH_MAX];
int has_context = 0;
int success = 0;
const char *arg = "";
ush_zero(&ctx, (u64)sizeof(ctx));
ush_zero(&ret, (u64)sizeof(ret));
ush_init_state(&sh);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
if (ush_command_ctx_read(&ctx) != 0) {
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "kdbg") != 0) {
has_context = 1;
arg = ctx.arg;
if (ctx.cwd[0] == '/') {
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
}
}
}
success = ush_cmd_kdbg(arg);
if (has_context != 0) {
if (ush_streq(sh.cwd, initial_cwd) == 0) {
ret.flags |= USH_CMD_RET_FLAG_CWD;
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
}
if (sh.exit_requested != 0) {
ret.flags |= USH_CMD_RET_FLAG_EXIT;
ret.exit_code = sh.exit_code;
}
(void)ush_command_ret_write(&ret);
}
return (success != 0) ? 0 : 1;
}

View File

@@ -156,6 +156,7 @@ static int ush_cmd_help(void) {
ush_writeln(" wait <pid> / fg [pid]"); ush_writeln(" wait <pid> / fg [pid]");
ush_writeln(" kill <pid> [signal]"); ush_writeln(" kill <pid> [signal]");
ush_writeln(" jobs [-a] / ps [-a] [-u] / top [--once] [-n loops] [-d ticks]"); ush_writeln(" jobs [-a] / ps [-a] [-u] / top [--once] [-n loops] [-d ticks]");
ush_writeln(" kdbg sym <addr> / kdbg bt <rbp> <rip> / kdbg regs");
ush_writeln(" sleep <ticks>"); ush_writeln(" sleep <ticks>");
ush_writeln(" yield"); ush_writeln(" yield");
ush_writeln(" shutdown / restart"); ush_writeln(" shutdown / restart");

View File

@@ -100,6 +100,9 @@ typedef struct cleonos_proc_snapshot {
#define CLEONOS_SYSCALL_PROC_PID_AT 62ULL #define CLEONOS_SYSCALL_PROC_PID_AT 62ULL
#define CLEONOS_SYSCALL_PROC_SNAPSHOT 63ULL #define CLEONOS_SYSCALL_PROC_SNAPSHOT 63ULL
#define CLEONOS_SYSCALL_PROC_KILL 64ULL #define CLEONOS_SYSCALL_PROC_KILL 64ULL
#define CLEONOS_SYSCALL_KDBG_SYM 65ULL
#define CLEONOS_SYSCALL_KDBG_BT 66ULL
#define CLEONOS_SYSCALL_KDBG_REGS 67ULL
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);
@@ -166,5 +169,8 @@ u64 cleonos_sys_proc_count(void);
u64 cleonos_sys_proc_pid_at(u64 index, u64 *out_pid); u64 cleonos_sys_proc_pid_at(u64 index, u64 *out_pid);
u64 cleonos_sys_proc_snapshot(u64 pid, cleonos_proc_snapshot *out_snapshot, u64 out_size); u64 cleonos_sys_proc_snapshot(u64 pid, cleonos_proc_snapshot *out_snapshot, u64 out_size);
u64 cleonos_sys_proc_kill(u64 pid, u64 signal); u64 cleonos_sys_proc_kill(u64 pid, u64 signal);
u64 cleonos_sys_kdbg_sym(u64 addr, char *out_line, u64 out_size);
u64 cleonos_sys_kdbg_bt(u64 rbp, u64 rip, char *out_text, u64 out_size);
u64 cleonos_sys_kdbg_regs(char *out_text, u64 out_size);
#endif #endif

View File

@@ -268,3 +268,29 @@ u64 cleonos_sys_proc_snapshot(u64 pid, cleonos_proc_snapshot *out_snapshot, u64
u64 cleonos_sys_proc_kill(u64 pid, u64 signal) { u64 cleonos_sys_proc_kill(u64 pid, u64 signal) {
return cleonos_syscall(CLEONOS_SYSCALL_PROC_KILL, pid, signal, 0ULL); return cleonos_syscall(CLEONOS_SYSCALL_PROC_KILL, pid, signal, 0ULL);
} }
struct cleonos_kdbg_bt_req {
u64 rbp;
u64 rip;
u64 out_ptr;
u64 out_size;
};
u64 cleonos_sys_kdbg_sym(u64 addr, char *out_line, u64 out_size) {
return cleonos_syscall(CLEONOS_SYSCALL_KDBG_SYM, addr, (u64)out_line, out_size);
}
u64 cleonos_sys_kdbg_bt(u64 rbp, u64 rip, char *out_text, u64 out_size) {
struct cleonos_kdbg_bt_req req;
req.rbp = rbp;
req.rip = rip;
req.out_ptr = (u64)out_text;
req.out_size = out_size;
return cleonos_syscall(CLEONOS_SYSCALL_KDBG_BT, (u64)&req, 0ULL, 0ULL);
}
u64 cleonos_sys_kdbg_regs(char *out_text, u64 out_size) {
return cleonos_syscall(CLEONOS_SYSCALL_KDBG_REGS, (u64)out_text, out_size, 0ULL);
}

View File

@@ -68,6 +68,9 @@
#define CLKS_SYSCALL_PROC_PID_AT 62ULL #define CLKS_SYSCALL_PROC_PID_AT 62ULL
#define CLKS_SYSCALL_PROC_SNAPSHOT 63ULL #define CLKS_SYSCALL_PROC_SNAPSHOT 63ULL
#define CLKS_SYSCALL_PROC_KILL 64ULL #define CLKS_SYSCALL_PROC_KILL 64ULL
#define CLKS_SYSCALL_KDBG_SYM 65ULL
#define CLKS_SYSCALL_KDBG_BT 66ULL
#define CLKS_SYSCALL_KDBG_REGS 67ULL
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

@@ -229,14 +229,19 @@ static clks_bool clks_panic_parse_symbol_line(const char *line,
usize len, usize len,
u64 *out_addr, u64 *out_addr,
const char **out_name, const char **out_name,
usize *out_name_len) { usize *out_name_len,
const char **out_source,
usize *out_source_len) {
usize i = 0U; usize i = 0U;
u64 addr = 0ULL; u64 addr = 0ULL;
u32 digits = 0U; u32 digits = 0U;
usize name_start; usize name_start;
usize name_end; usize name_end;
usize source_start;
usize source_end;
if (line == CLKS_NULL || out_addr == CLKS_NULL || out_name == CLKS_NULL || out_name_len == CLKS_NULL) { if (line == CLKS_NULL || out_addr == CLKS_NULL || out_name == CLKS_NULL || out_name_len == CLKS_NULL ||
out_source == CLKS_NULL || out_source_len == CLKS_NULL) {
return CLKS_FALSE; return CLKS_FALSE;
} }
@@ -267,20 +272,34 @@ static clks_bool clks_panic_parse_symbol_line(const char *line,
} }
name_start = i; name_start = i;
name_end = len;
while (name_end > name_start && while (i < len && line[i] != ' ' && line[i] != '\t' && line[i] != '\r') {
(line[name_end - 1U] == ' ' || line[name_end - 1U] == '\t' || line[name_end - 1U] == '\r')) { i++;
name_end--;
} }
name_end = i;
if (name_end <= name_start) { if (name_end <= name_start) {
return CLKS_FALSE; return CLKS_FALSE;
} }
while (i < len && (line[i] == ' ' || line[i] == '\t')) {
i++;
}
source_start = i;
source_end = len;
while (source_end > source_start &&
(line[source_end - 1U] == ' ' || line[source_end - 1U] == '\t' || line[source_end - 1U] == '\r')) {
source_end--;
}
*out_addr = addr; *out_addr = addr;
*out_name = &line[name_start]; *out_name = &line[name_start];
*out_name_len = name_end - name_start; *out_name_len = name_end - name_start;
*out_source = (source_end > source_start) ? &line[source_start] : CLKS_NULL;
*out_source_len = (source_end > source_start) ? (source_end - source_start) : 0U;
return CLKS_TRUE; return CLKS_TRUE;
} }
@@ -309,22 +328,32 @@ static clks_bool clks_panic_symbols_ready(void) {
return CLKS_TRUE; return CLKS_TRUE;
} }
static clks_bool clks_panic_lookup_symbol(u64 addr, const char **out_name, usize *out_name_len, u64 *out_base) { static clks_bool clks_panic_lookup_symbol(u64 addr,
const char **out_name,
usize *out_name_len,
u64 *out_base,
const char **out_source,
usize *out_source_len) {
const char *data; const char *data;
const char *end; const char *end;
const char *line; const char *line;
const char *best_name = CLKS_NULL; const char *best_name = CLKS_NULL;
const char *best_source = CLKS_NULL;
usize best_len = 0U; usize best_len = 0U;
usize best_source_len = 0U;
u64 best_addr = 0ULL; u64 best_addr = 0ULL;
clks_bool found = CLKS_FALSE; clks_bool found = CLKS_FALSE;
if (out_name == CLKS_NULL || out_name_len == CLKS_NULL || out_base == CLKS_NULL) { if (out_name == CLKS_NULL || out_name_len == CLKS_NULL || out_base == CLKS_NULL || out_source == CLKS_NULL ||
out_source_len == CLKS_NULL) {
return CLKS_FALSE; return CLKS_FALSE;
} }
*out_name = CLKS_NULL; *out_name = CLKS_NULL;
*out_name_len = 0U; *out_name_len = 0U;
*out_base = 0ULL; *out_base = 0ULL;
*out_source = CLKS_NULL;
*out_source_len = 0U;
if (clks_panic_symbols_ready() == CLKS_FALSE) { if (clks_panic_symbols_ready() == CLKS_FALSE) {
return CLKS_FALSE; return CLKS_FALSE;
@@ -337,6 +366,8 @@ static clks_bool clks_panic_lookup_symbol(u64 addr, const char **out_name, usize
u64 line_addr; u64 line_addr;
const char *line_name; const char *line_name;
usize line_name_len; usize line_name_len;
const char *line_source;
usize line_source_len;
usize line_len = 0U; usize line_len = 0U;
line = data; line = data;
@@ -350,7 +381,13 @@ static clks_bool clks_panic_lookup_symbol(u64 addr, const char **out_name, usize
data++; data++;
} }
if (clks_panic_parse_symbol_line(line, line_len, &line_addr, &line_name, &line_name_len) == CLKS_FALSE) { if (clks_panic_parse_symbol_line(line,
line_len,
&line_addr,
&line_name,
&line_name_len,
&line_source,
&line_source_len) == CLKS_FALSE) {
continue; continue;
} }
@@ -358,6 +395,8 @@ static clks_bool clks_panic_lookup_symbol(u64 addr, const char **out_name, usize
best_addr = line_addr; best_addr = line_addr;
best_name = line_name; best_name = line_name;
best_len = line_name_len; best_len = line_name_len;
best_source = line_source;
best_source_len = line_source_len;
found = CLKS_TRUE; found = CLKS_TRUE;
} }
} }
@@ -369,6 +408,8 @@ static clks_bool clks_panic_lookup_symbol(u64 addr, const char **out_name, usize
*out_name = best_name; *out_name = best_name;
*out_name_len = best_len; *out_name_len = best_len;
*out_base = best_addr; *out_base = best_addr;
*out_source = best_source;
*out_source_len = best_source_len;
return CLKS_TRUE; return CLKS_TRUE;
} }
@@ -376,13 +417,15 @@ static void clks_panic_emit_bt_entry(struct clks_panic_console *console, u32 ind
char index_dec[12]; char index_dec[12];
char rip_hex[19]; char rip_hex[19];
const char *sym_name = CLKS_NULL; const char *sym_name = CLKS_NULL;
const char *sym_source = CLKS_NULL;
usize sym_name_len = 0U; usize sym_name_len = 0U;
usize sym_source_len = 0U;
u64 sym_base = 0ULL; u64 sym_base = 0ULL;
clks_bool has_symbol; clks_bool has_symbol;
clks_panic_u32_to_dec(index, index_dec, sizeof(index_dec)); clks_panic_u32_to_dec(index, index_dec, sizeof(index_dec));
clks_panic_u64_to_hex(rip, rip_hex); clks_panic_u64_to_hex(rip, rip_hex);
has_symbol = clks_panic_lookup_symbol(rip, &sym_name, &sym_name_len, &sym_base); has_symbol = clks_panic_lookup_symbol(rip, &sym_name, &sym_name_len, &sym_base, &sym_source, &sym_source_len);
clks_serial_write("[PANIC][BT] #"); clks_serial_write("[PANIC][BT] #");
clks_serial_write(index_dec); clks_serial_write(index_dec);
@@ -398,6 +441,11 @@ static void clks_panic_emit_bt_entry(struct clks_panic_console *console, u32 ind
clks_panic_serial_write_n(sym_name, sym_name_len); clks_panic_serial_write_n(sym_name, sym_name_len);
clks_serial_write("+"); clks_serial_write("+");
clks_serial_write(off_hex); clks_serial_write(off_hex);
if (sym_source != CLKS_NULL && sym_source_len > 0U) {
clks_serial_write(" @ ");
clks_panic_serial_write_n(sym_source, sym_source_len);
}
} }
clks_serial_write("\n"); clks_serial_write("\n");
@@ -420,6 +468,11 @@ static void clks_panic_emit_bt_entry(struct clks_panic_console *console, u32 ind
clks_panic_console_write_n(console, sym_name, sym_name_len); clks_panic_console_write_n(console, sym_name, sym_name_len);
clks_panic_console_write(console, "+"); clks_panic_console_write(console, "+");
clks_panic_console_write(console, off_hex); clks_panic_console_write(console, off_hex);
if (sym_source != CLKS_NULL && sym_source_len > 0U) {
clks_panic_console_write(console, " @ ");
clks_panic_console_write_n(console, sym_source, sym_source_len);
}
} }
clks_panic_console_write(console, "\n"); clks_panic_console_write(console, "\n");

View File

@@ -27,6 +27,11 @@
#define CLKS_SYSCALL_ITEM_MAX 128U #define CLKS_SYSCALL_ITEM_MAX 128U
#define CLKS_SYSCALL_PROCFS_TEXT_MAX 2048U #define CLKS_SYSCALL_PROCFS_TEXT_MAX 2048U
#define CLKS_SYSCALL_USER_TRACE_BUDGET 128ULL #define CLKS_SYSCALL_USER_TRACE_BUDGET 128ULL
#define CLKS_SYSCALL_KDBG_TEXT_MAX 2048U
#define CLKS_SYSCALL_KDBG_BT_MAX_FRAMES 16U
#define CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES (128ULL * 1024ULL)
#define CLKS_SYSCALL_KERNEL_SYMBOL_FILE "/system/kernel.sym"
#define CLKS_SYSCALL_KERNEL_ADDR_BASE 0xFFFF800000000000ULL
struct clks_syscall_frame { struct clks_syscall_frame {
u64 rax; u64 rax;
@@ -53,9 +58,21 @@ struct clks_syscall_frame {
u64 ss; u64 ss;
}; };
struct clks_syscall_kdbg_bt_req {
u64 rbp;
u64 rip;
u64 out_ptr;
u64 out_size;
};
static clks_bool clks_syscall_ready = CLKS_FALSE; static clks_bool clks_syscall_ready = CLKS_FALSE;
static clks_bool clks_syscall_user_trace_active = CLKS_FALSE; static clks_bool clks_syscall_user_trace_active = CLKS_FALSE;
static u64 clks_syscall_user_trace_budget = 0ULL; static u64 clks_syscall_user_trace_budget = 0ULL;
static struct clks_syscall_frame clks_syscall_last_frame;
static clks_bool clks_syscall_last_frame_valid = CLKS_FALSE;
static clks_bool clks_syscall_symbols_checked = CLKS_FALSE;
static const char *clks_syscall_symbols_data = CLKS_NULL;
static u64 clks_syscall_symbols_size = 0ULL;
#if defined(CLKS_ARCH_X86_64) #if defined(CLKS_ARCH_X86_64)
static inline void clks_syscall_outb(u16 port, u8 value) { static inline void clks_syscall_outb(u16 port, u8 value) {
@@ -104,6 +121,24 @@ static clks_bool clks_syscall_copy_user_optional_string(u64 src_addr, char *dst,
return clks_syscall_copy_user_string(src_addr, dst, dst_size); return clks_syscall_copy_user_string(src_addr, dst, dst_size);
} }
static u64 clks_syscall_copy_text_to_user(u64 dst_addr, u64 dst_size, const char *src, usize src_len) {
usize copy_len;
if (dst_addr == 0ULL || dst_size == 0ULL || src == CLKS_NULL) {
return 0ULL;
}
copy_len = src_len;
if (copy_len + 1U > (usize)dst_size) {
copy_len = (usize)dst_size - 1U;
}
clks_memcpy((void *)dst_addr, src, copy_len);
((char *)dst_addr)[copy_len] = '\0';
return (u64)copy_len;
}
static u64 clks_syscall_log_write(u64 arg0, u64 arg1) { static u64 clks_syscall_log_write(u64 arg0, u64 arg1) {
const char *src = (const char *)arg0; const char *src = (const char *)arg0;
u64 len = arg1; u64 len = arg1;
@@ -336,6 +371,461 @@ static usize clks_syscall_procfs_append_u64_hex(char *out, usize out_size, usize
return pos; return pos;
} }
static usize clks_syscall_procfs_append_n(char *out, usize out_size, usize pos, const char *text, usize text_len) {
usize i = 0U;
if (text == CLKS_NULL) {
return pos;
}
while (i < text_len) {
pos = clks_syscall_procfs_append_char(out, out_size, pos, text[i]);
i++;
}
return pos;
}
static clks_bool clks_syscall_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_syscall_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_syscall_parse_symbol_line(const char *line,
usize len,
u64 *out_addr,
const char **out_name,
usize *out_name_len,
const char **out_source,
usize *out_source_len) {
usize i = 0U;
u64 addr = 0ULL;
u32 digits = 0U;
usize name_start;
usize name_end;
usize source_start;
usize source_end;
if (line == CLKS_NULL || out_addr == CLKS_NULL || out_name == CLKS_NULL || out_name_len == CLKS_NULL ||
out_source == CLKS_NULL || out_source_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_syscall_is_hex(line[i]) == CLKS_TRUE) {
addr = (addr << 4) | (u64)clks_syscall_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;
while (i < len && line[i] != ' ' && line[i] != '\t' && line[i] != '\r') {
i++;
}
name_end = i;
if (name_end <= name_start) {
return CLKS_FALSE;
}
while (i < len && (line[i] == ' ' || line[i] == '\t')) {
i++;
}
source_start = i;
source_end = len;
while (source_end > source_start &&
(line[source_end - 1U] == ' ' || line[source_end - 1U] == '\t' || line[source_end - 1U] == '\r')) {
source_end--;
}
*out_addr = addr;
*out_name = &line[name_start];
*out_name_len = name_end - name_start;
*out_source = (source_end > source_start) ? &line[source_start] : CLKS_NULL;
*out_source_len = (source_end > source_start) ? (source_end - source_start) : 0U;
return CLKS_TRUE;
}
static clks_bool clks_syscall_symbols_ready(void) {
const void *data;
u64 size = 0ULL;
if (clks_syscall_symbols_checked == CLKS_TRUE) {
return (clks_syscall_symbols_data != CLKS_NULL && clks_syscall_symbols_size > 0ULL) ? CLKS_TRUE : CLKS_FALSE;
}
clks_syscall_symbols_checked = CLKS_TRUE;
if (clks_fs_is_ready() == CLKS_FALSE) {
return CLKS_FALSE;
}
data = clks_fs_read_all(CLKS_SYSCALL_KERNEL_SYMBOL_FILE, &size);
if (data == CLKS_NULL || size == 0ULL) {
return CLKS_FALSE;
}
clks_syscall_symbols_data = (const char *)data;
clks_syscall_symbols_size = size;
return CLKS_TRUE;
}
static clks_bool clks_syscall_lookup_symbol(u64 addr,
const char **out_name,
usize *out_name_len,
u64 *out_base,
const char **out_source,
usize *out_source_len) {
const char *data;
const char *end;
const char *line;
const char *best_name = CLKS_NULL;
const char *best_source = CLKS_NULL;
usize best_name_len = 0U;
usize best_source_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 || out_source == CLKS_NULL ||
out_source_len == CLKS_NULL) {
return CLKS_FALSE;
}
*out_name = CLKS_NULL;
*out_name_len = 0U;
*out_base = 0ULL;
*out_source = CLKS_NULL;
*out_source_len = 0U;
if (clks_syscall_symbols_ready() == CLKS_FALSE) {
return CLKS_FALSE;
}
data = clks_syscall_symbols_data;
end = clks_syscall_symbols_data + clks_syscall_symbols_size;
while (data < end) {
u64 line_addr;
const char *line_name;
usize line_name_len;
const char *line_source;
usize line_source_len;
usize line_len = 0U;
line = data;
while (data < end && *data != '\n') {
data++;
line_len++;
}
if (data < end && *data == '\n') {
data++;
}
if (clks_syscall_parse_symbol_line(line,
line_len,
&line_addr,
&line_name,
&line_name_len,
&line_source,
&line_source_len) == CLKS_FALSE) {
continue;
}
if (line_addr <= addr && (found == CLKS_FALSE || line_addr >= best_addr)) {
best_addr = line_addr;
best_name = line_name;
best_name_len = line_name_len;
best_source = line_source;
best_source_len = line_source_len;
found = CLKS_TRUE;
}
}
if (found == CLKS_FALSE) {
return CLKS_FALSE;
}
*out_name = best_name;
*out_name_len = best_name_len;
*out_base = best_addr;
*out_source = best_source;
*out_source_len = best_source_len;
return CLKS_TRUE;
}
static usize clks_syscall_kdbg_format_symbol_into(char *out, usize out_size, usize pos, u64 addr) {
const char *sym_name = CLKS_NULL;
const char *sym_source = CLKS_NULL;
usize sym_name_len = 0U;
usize sym_source_len = 0U;
u64 sym_base = 0ULL;
clks_bool has_symbol;
pos = clks_syscall_procfs_append_u64_hex(out, out_size, pos, addr);
has_symbol = clks_syscall_lookup_symbol(addr, &sym_name, &sym_name_len, &sym_base, &sym_source, &sym_source_len);
if (has_symbol == CLKS_TRUE) {
pos = clks_syscall_procfs_append_char(out, out_size, pos, ' ');
pos = clks_syscall_procfs_append_n(out, out_size, pos, sym_name, sym_name_len);
pos = clks_syscall_procfs_append_char(out, out_size, pos, '+');
pos = clks_syscall_procfs_append_u64_hex(out, out_size, pos, addr - sym_base);
if (sym_source != CLKS_NULL && sym_source_len > 0U) {
pos = clks_syscall_procfs_append_text(out, out_size, pos, " @ ");
pos = clks_syscall_procfs_append_n(out, out_size, pos, sym_source, sym_source_len);
}
} else {
pos = clks_syscall_procfs_append_text(out, out_size, pos, " <no-symbol>");
}
return pos;
}
static usize clks_syscall_kdbg_append_bt_frame(char *out, usize out_size, usize pos, u64 index, u64 rip) {
pos = clks_syscall_procfs_append_char(out, out_size, pos, '#');
pos = clks_syscall_procfs_append_u64_dec(out, out_size, pos, index);
pos = clks_syscall_procfs_append_char(out, out_size, pos, ' ');
pos = clks_syscall_kdbg_format_symbol_into(out, out_size, pos, rip);
pos = clks_syscall_procfs_append_char(out, out_size, pos, '\n');
return pos;
}
static clks_bool clks_syscall_kdbg_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_SYSCALL_KERNEL_ADDR_BASE) {
return CLKS_FALSE;
}
return CLKS_TRUE;
}
static u64 clks_syscall_kdbg_sym(u64 arg0, u64 arg1, u64 arg2) {
char text[CLKS_SYSCALL_KDBG_TEXT_MAX];
usize len;
if (arg1 == 0ULL || arg2 == 0ULL) {
return 0ULL;
}
text[0] = '\0';
len = clks_syscall_kdbg_format_symbol_into(text, sizeof(text), 0U, arg0);
return clks_syscall_copy_text_to_user(arg1, arg2, text, len);
}
static u64 clks_syscall_kdbg_regs(u64 arg0, u64 arg1) {
char text[CLKS_SYSCALL_KDBG_TEXT_MAX];
usize pos = 0U;
const struct clks_syscall_frame *frame = &clks_syscall_last_frame;
if (arg0 == 0ULL || arg1 == 0ULL) {
return 0ULL;
}
text[0] = '\0';
if (clks_syscall_last_frame_valid == CLKS_FALSE) {
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, "NO REG SNAPSHOT\n");
return clks_syscall_copy_text_to_user(arg0, arg1, text, pos);
}
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, "RAX=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->rax);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " RBX=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->rbx);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " RCX=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->rcx);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " RDX=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->rdx);
pos = clks_syscall_procfs_append_char(text, sizeof(text), pos, '\n');
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, "RSI=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->rsi);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " RDI=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->rdi);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " RBP=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->rbp);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " RSP=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->rsp);
pos = clks_syscall_procfs_append_char(text, sizeof(text), pos, '\n');
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, "R8 =");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->r8);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " R9 =");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->r9);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " R10=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->r10);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " R11=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->r11);
pos = clks_syscall_procfs_append_char(text, sizeof(text), pos, '\n');
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, "R12=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->r12);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " R13=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->r13);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " R14=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->r14);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " R15=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->r15);
pos = clks_syscall_procfs_append_char(text, sizeof(text), pos, '\n');
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, "RIP=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->rip);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " CS=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->cs);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " RFLAGS=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->rflags);
pos = clks_syscall_procfs_append_char(text, sizeof(text), pos, '\n');
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, "VECTOR=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->vector);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " ERROR=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->error_code);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " SS=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, frame->ss);
pos = clks_syscall_procfs_append_char(text, sizeof(text), pos, '\n');
return clks_syscall_copy_text_to_user(arg0, arg1, text, pos);
}
static u64 clks_syscall_kdbg_bt(u64 arg0) {
struct clks_syscall_kdbg_bt_req req;
char text[CLKS_SYSCALL_KDBG_TEXT_MAX];
usize pos = 0U;
u64 frame_index = 0ULL;
if (arg0 == 0ULL) {
return 0ULL;
}
clks_memcpy(&req, (const void *)arg0, sizeof(req));
if (req.out_ptr == 0ULL || req.out_size == 0ULL) {
return 0ULL;
}
text[0] = '\0';
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, "BT RBP=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, req.rbp);
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, " RIP=");
pos = clks_syscall_procfs_append_u64_hex(text, sizeof(text), pos, req.rip);
pos = clks_syscall_procfs_append_char(text, sizeof(text), pos, '\n');
if (req.rip != 0ULL) {
pos = clks_syscall_kdbg_append_bt_frame(text, sizeof(text), pos, frame_index, req.rip);
frame_index++;
}
#if defined(CLKS_ARCH_X86_64)
{
u64 current_rbp = req.rbp;
u64 current_rsp = 0ULL;
u64 stack_low;
u64 stack_high;
__asm__ volatile("mov %%rsp, %0" : "=r"(current_rsp));
stack_low = (current_rsp > CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES)
? (current_rsp - CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES)
: CLKS_SYSCALL_KERNEL_ADDR_BASE;
stack_high = current_rsp + CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES;
if (stack_high < current_rsp) {
stack_high = 0xFFFFFFFFFFFFFFFFULL;
}
if (stack_low < CLKS_SYSCALL_KERNEL_ADDR_BASE) {
stack_low = CLKS_SYSCALL_KERNEL_ADDR_BASE;
}
if (clks_syscall_kdbg_stack_ptr_valid(current_rbp, stack_low, stack_high) == CLKS_TRUE) {
while (frame_index < CLKS_SYSCALL_KDBG_BT_MAX_FRAMES) {
const u64 *frame_ptr;
u64 next_rbp;
u64 ret_rip;
frame_ptr = (const u64 *)(usize)current_rbp;
next_rbp = frame_ptr[0];
ret_rip = frame_ptr[1];
if (ret_rip == 0ULL) {
break;
}
pos = clks_syscall_kdbg_append_bt_frame(text, sizeof(text), pos, frame_index, ret_rip);
frame_index++;
if (next_rbp <= current_rbp) {
break;
}
if (clks_syscall_kdbg_stack_ptr_valid(next_rbp, stack_low, stack_high) == CLKS_FALSE) {
break;
}
current_rbp = next_rbp;
}
} else {
pos = clks_syscall_procfs_append_text(text,
sizeof(text),
pos,
"NOTE: stack walk skipped (rbp not in current kernel stack window)\n");
}
}
#else
pos = clks_syscall_procfs_append_text(text, sizeof(text), pos, "NOTE: stack walk unsupported on this arch\n");
#endif
return clks_syscall_copy_text_to_user(req.out_ptr, req.out_size, text, pos);
}
static clks_bool clks_syscall_procfs_snapshot_for_path(const char *path, struct clks_exec_proc_snapshot *out_snap) { static clks_bool clks_syscall_procfs_snapshot_for_path(const char *path, struct clks_exec_proc_snapshot *out_snap) {
u64 pid; u64 pid;
@@ -1043,6 +1533,11 @@ void clks_syscall_init(void) {
clks_syscall_ready = CLKS_TRUE; clks_syscall_ready = CLKS_TRUE;
clks_syscall_user_trace_active = CLKS_FALSE; clks_syscall_user_trace_active = CLKS_FALSE;
clks_syscall_user_trace_budget = 0ULL; clks_syscall_user_trace_budget = 0ULL;
clks_memset(&clks_syscall_last_frame, 0, sizeof(clks_syscall_last_frame));
clks_syscall_last_frame_valid = CLKS_FALSE;
clks_syscall_symbols_checked = CLKS_FALSE;
clks_syscall_symbols_data = CLKS_NULL;
clks_syscall_symbols_size = 0ULL;
clks_log(CLKS_LOG_INFO, "SYSCALL", "INT80 FRAMEWORK ONLINE"); clks_log(CLKS_LOG_INFO, "SYSCALL", "INT80 FRAMEWORK ONLINE");
} }
@@ -1054,6 +1549,9 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
return (u64)-1; return (u64)-1;
} }
clks_memcpy(&clks_syscall_last_frame, frame, sizeof(clks_syscall_last_frame));
clks_syscall_last_frame_valid = CLKS_TRUE;
id = frame->rax; id = frame->rax;
clks_syscall_trace_user_program(id); clks_syscall_trace_user_program(id);
@@ -1195,6 +1693,12 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
return clks_syscall_audio_play_tone(frame->rbx, frame->rcx); return clks_syscall_audio_play_tone(frame->rbx, frame->rcx);
case CLKS_SYSCALL_AUDIO_STOP: case CLKS_SYSCALL_AUDIO_STOP:
return clks_syscall_audio_stop(); return clks_syscall_audio_stop();
case CLKS_SYSCALL_KDBG_SYM:
return clks_syscall_kdbg_sym(frame->rbx, frame->rcx, frame->rdx);
case CLKS_SYSCALL_KDBG_BT:
return clks_syscall_kdbg_bt(frame->rbx);
case CLKS_SYSCALL_KDBG_REGS:
return clks_syscall_kdbg_regs(frame->rbx, frame->rcx);
default: default:
return (u64)-1; return (u64)-1;
} }

View File

@@ -30,6 +30,7 @@ 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("${NM_TOOL}")
require_tool("${ADDR2LINE_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}")

View File

@@ -4,6 +4,10 @@ if(NOT DEFINED NM_TOOL OR "${NM_TOOL}" STREQUAL "")
message(FATAL_ERROR "NM_TOOL is required") message(FATAL_ERROR "NM_TOOL is required")
endif() endif()
if(NOT DEFINED ADDR2LINE_TOOL OR "${ADDR2LINE_TOOL}" STREQUAL "")
message(FATAL_ERROR "ADDR2LINE_TOOL is required")
endif()
if(NOT DEFINED KERNEL_ELF OR "${KERNEL_ELF}" STREQUAL "") if(NOT DEFINED KERNEL_ELF OR "${KERNEL_ELF}" STREQUAL "")
message(FATAL_ERROR "KERNEL_ELF is required") message(FATAL_ERROR "KERNEL_ELF is required")
endif() endif()
@@ -27,7 +31,9 @@ string(REPLACE "\r\n" "\n" _nm_output "${_nm_output}")
string(REPLACE "\r" "\n" _nm_output "${_nm_output}") string(REPLACE "\r" "\n" _nm_output "${_nm_output}")
string(REPLACE "\n" ";" _nm_lines "${_nm_output}") string(REPLACE "\n" ";" _nm_lines "${_nm_output}")
set(_out_text "CLEONOS_KERNEL_SYMBOLS_V1\n") set(_symbol_addrs_upper)
set(_symbol_addrs_query)
set(_symbol_names)
foreach(_line IN LISTS _nm_lines) foreach(_line IN LISTS _nm_lines)
string(STRIP "${_line}" _line) string(STRIP "${_line}" _line)
@@ -45,8 +51,55 @@ foreach(_line IN LISTS _nm_lines)
endif() endif()
string(TOUPPER "${_addr}" _addr_upper) string(TOUPPER "${_addr}" _addr_upper)
set(_out_text "${_out_text}0X${_addr_upper} ${_name}\n") list(APPEND _symbol_addrs_upper "${_addr_upper}")
list(APPEND _symbol_addrs_query "0x${_addr_upper}")
list(APPEND _symbol_names "${_name}")
endif() endif()
endforeach() endforeach()
set(_out_text "CLEONOS_KERNEL_SYMBOLS_V2\n")
list(LENGTH _symbol_addrs_query _symbol_count)
if(_symbol_count GREATER 0)
execute_process(
COMMAND "${ADDR2LINE_TOOL}" -f -C -e "${KERNEL_ELF}" ${_symbol_addrs_query}
RESULT_VARIABLE _a2l_result
OUTPUT_VARIABLE _a2l_output
ERROR_VARIABLE _a2l_error
)
if(NOT _a2l_result EQUAL 0)
message(FATAL_ERROR "failed to run addr2line (${_a2l_result}): ${_a2l_error}")
endif()
string(REPLACE "\r\n" "\n" _a2l_output "${_a2l_output}")
string(REPLACE "\r" "\n" _a2l_output "${_a2l_output}")
string(REPLACE "\n" ";" _a2l_lines "${_a2l_output}")
list(LENGTH _a2l_lines _a2l_line_count)
math(EXPR _last_index "${_symbol_count} - 1")
foreach(_idx RANGE 0 ${_last_index})
math(EXPR _src_idx "${_idx} * 2 + 1")
list(GET _symbol_addrs_upper ${_idx} _addr_upper)
list(GET _symbol_names ${_idx} _name)
if(_src_idx LESS _a2l_line_count)
list(GET _a2l_lines ${_src_idx} _src_line)
else()
set(_src_line "??:0")
endif()
string(STRIP "${_src_line}" _src_line)
if("${_src_line}" STREQUAL "")
set(_src_line "??:0")
endif()
string(REPLACE "\t" " " _src_line "${_src_line}")
set(_out_text "${_out_text}0X${_addr_upper}\t${_name}\t${_src_line}\n")
endforeach()
endif()
file(WRITE "${OUT_SYMBOL_FILE}" "${_out_text}") file(WRITE "${OUT_SYMBOL_FILE}" "${_out_text}")