From d3c1d6cc3490147cba4a657441d8b35cfd389529 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Mon, 12 Aug 2024 19:40:20 -0700 Subject: [PATCH] [kernel] Add debug names to processes To make debugging easier, add names to processes. These are arbitrary and supplied by the caller of process_create. The max is 31 characters in debug configuration, and 0 in release. --- definitions/objects/process.def | 4 +- src/kernel/kernel_main.cpp | 2 +- src/kernel/objects/process.cpp | 16 ++++++- src/kernel/objects/process.h | 22 ++++++++- src/kernel/panic.serial/display.cpp | 73 ++++++++++++++++++++++------- src/kernel/syscalls/process.cpp | 4 +- src/kernel/syscalls/system.cpp | 3 +- src/user/srv.init/loader.cpp | 6 +-- 8 files changed, 104 insertions(+), 26 deletions(-) diff --git a/definitions/objects/process.def b/definitions/objects/process.def index e4f0b7a..ac57083 100644 --- a/definitions/objects/process.def +++ b/definitions/objects/process.def @@ -12,7 +12,9 @@ object process : object { ] # Create a new empty process - method create [constructor] + method create [constructor] { + param name string + } # Stop all threads and exit the given process method kill [destructor cap:kill] diff --git a/src/kernel/kernel_main.cpp b/src/kernel/kernel_main.cpp index de4cfe7..b65a26b 100644 --- a/src/kernel/kernel_main.cpp +++ b/src/kernel/kernel_main.cpp @@ -86,7 +86,7 @@ load_init_server(bootproto::program &program, uintptr_t modules_address) using bootproto::section_flags; using obj::vm_flags; - obj::process *p = new obj::process; + obj::process *p = new obj::process {"srv.init"}; j6_handle_t sys_handle = g_cap_table.create(&obj::system::get(), obj::system::init_caps); diff --git a/src/kernel/objects/process.cpp b/src/kernel/objects/process.cpp index 05b038b..0b2cf31 100644 --- a/src/kernel/objects/process.cpp +++ b/src/kernel/objects/process.cpp @@ -1,3 +1,4 @@ +#include #include #include "kassert.h" @@ -18,10 +19,18 @@ obj::process &g_kernel_process = __g_kernel_process_storage.value; namespace obj { -process::process() : +process::process(const char *name) : kobject {kobject::type::process}, m_state {state::running} { + if constexpr(__use_process_names) { + memset(m_name, 0, sizeof(m_name)); + if (name) { + static constexpr size_t charlen = sizeof(m_name) - 1; + for (size_t i = 0; i < charlen && name[i]; ++i) + m_name[i] = name[i]; + } + } } // The "kernel process"-only constructor @@ -30,6 +39,11 @@ process::process(page_table *kpml4) : m_space {kpml4}, m_state {state::running} { + if constexpr(__use_process_names) { + static constexpr char kernel[] = "KERNEL"; + memcpy(m_name, kernel, sizeof(kernel)); + memset(m_name + sizeof(kernel), 0, sizeof(m_name) - sizeof(kernel)); + } } process::~process() diff --git a/src/kernel/objects/process.h b/src/kernel/objects/process.h index 13855c2..e52ae89 100644 --- a/src/kernel/objects/process.h +++ b/src/kernel/objects/process.h @@ -13,6 +13,14 @@ namespace obj { +static constexpr bool __use_process_names = +#ifdef __jsix_config_debug + true; +#else + false; +#endif + + class process : public kobject { @@ -32,7 +40,7 @@ public: static constexpr kobject::type type = kobject::type::process; /// Constructor. - process(); + process(const char *name); /// Destructor. virtual ~process(); @@ -47,6 +55,9 @@ public: /// Get the process' virtual memory space vm_space & space() { return m_space; } + /// Get the debugging name of the process + const char *name() { if constexpr(__use_process_names) return m_name; else return nullptr; } + /// Create a new thread in this process /// \args rsp3 If non-zero, sets the ring3 stack pointer to this value /// \args priority The new thread's scheduling priority @@ -107,6 +118,15 @@ private: enum class state : uint8_t { running, exited }; state m_state; + + static constexpr size_t max_name_len = +#ifdef __jsix_config_debug + 32; +#else + 0; +#endif + + char m_name[max_name_len]; }; } // namespace obj diff --git a/src/kernel/panic.serial/display.cpp b/src/kernel/panic.serial/display.cpp index 75300f1..d6f2308 100644 --- a/src/kernel/panic.serial/display.cpp +++ b/src/kernel/panic.serial/display.cpp @@ -2,6 +2,7 @@ #include "cpu.h" #include "display.h" +#include "kernel.dir/memory.h" #include "objects/process.h" #include "objects/thread.h" #include "serial.h" @@ -9,6 +10,44 @@ namespace panicking { +template inline bool +check_pointer(T p) +{ + static constexpr uint64_t large_flag = (1<<7); + static constexpr uint64_t pointer_mask = 0x0000fffffffff000; + static constexpr uintptr_t canon_mask = 0xffff800000000000; + + uintptr_t addr = reinterpret_cast(p); + + uintptr_t canon_bits = addr & canon_mask; + if (canon_bits && canon_bits != canon_mask) + return false; + + uintptr_t pml4 = 0; + asm volatile ( "mov %%cr3, %0" : "=r" (pml4) ); + pml4 += mem::linear_offset; + + uint64_t *table = reinterpret_cast(pml4); + unsigned shift = 39; + + while (table) { + unsigned index = (addr >> shift) & 0x1ffull; + uint64_t entry = table[index]; + + if ((entry & 0x1) == 0) + return false; + + if ((entry & large_flag) || shift <= 12) + return true; + + uint64_t next = (entry & pointer_mask) + mem::linear_offset; + table = reinterpret_cast(next); + shift -= 9; + } + + return false; +} + const char *clear = "\e[0m\n"; void @@ -40,23 +79,17 @@ print_cpu(serial_port &out, cpu_data &cpu) { uint32_t process = cpu.process ? cpu.process->obj_id() : 0; uint32_t thread = cpu.thread ? cpu.thread->obj_id() : 0; + const char *name = cpu.process ? cpu.process->name() : ""; out.write("\n \e[0;31m==[ CPU: "); char buffer[64]; - util::format({buffer, sizeof(buffer)}, "%4d <%02lx:%02lx>", - cpu.id + 1, process, thread); + size_t len = util::format({buffer, sizeof(buffer)}, "%4d <%02lx:%02lx> ]: %s ", + cpu.id + 1, process, thread, name); out.write(buffer); - out.write(" ]=============================================================\n"); -} - -template inline bool -canonical(T p) -{ - static constexpr uintptr_t mask = 0xffff800000000000; - uintptr_t addr = reinterpret_cast(p); - return (addr & mask) == mask || (addr & mask) == 0; + for (size_t i = 0; i < (74-len); ++i) out.write("="); + out.write("\n"); } void @@ -65,18 +98,26 @@ print_callstack(serial_port &out, symbol_table &syms, frame const *fp) char message[512]; unsigned count = 0; - while (canonical(fp) && fp && fp->return_addr) { - char const *name = syms.find_symbol(fp->return_addr); + while (fp && check_pointer(fp)) { + const uintptr_t ret = fp->return_addr; + char const *name = ret ? syms.find_symbol(ret) : ""; if (!name) - name = canonical(fp->return_addr) ? "" : ""; + name = check_pointer(fp->return_addr) ? "" : ""; util::format({message, sizeof(message)}, - " \e[0;33mframe %2d: <0x%016lx> \e[1;33m%s\n", - count++, fp->return_addr, name); + " \e[0;33mframe %2d: <0x%016lx> <0x%016lx> \e[1;33m%s\n", + count++, fp, fp->return_addr, name); out.write(message); + + if (!ret) return; fp = fp->prev; } + + const char *result = fp ? " " : ""; + util::format({message, sizeof(message)}, " \e[0mfinal <0x%016lx>%s\n", + fp, result); + out.write(message); } static void diff --git a/src/kernel/syscalls/process.cpp b/src/kernel/syscalls/process.cpp index 2c61d32..c3c7e01 100644 --- a/src/kernel/syscalls/process.cpp +++ b/src/kernel/syscalls/process.cpp @@ -10,9 +10,9 @@ using namespace obj; namespace syscalls { j6_status_t -process_create(j6_handle_t *self) +process_create(j6_handle_t *self, const char *path) { - process *p = construct_handle(self); + process *p = construct_handle(self, path); log::info(logs::task, "Process <%02lx> created", p->obj_id()); return j6_status_ok; } diff --git a/src/kernel/syscalls/system.cpp b/src/kernel/syscalls/system.cpp index ec26a6a..6a0da33 100644 --- a/src/kernel/syscalls/system.cpp +++ b/src/kernel/syscalls/system.cpp @@ -23,9 +23,10 @@ using system = class ::system; j6_status_t log(uint8_t area, uint8_t severity, const char *message) { + const char *name = process::current().name(); thread &th = thread::current(); log::log(static_cast(area), static_cast(severity), - "<%02lx:%02lx>: %s", th.parent().obj_id(), th.obj_id(), message); + "<%02lx:%02lx> %s: %s", th.parent().obj_id(), th.obj_id(), name, message); return j6_status_ok; } diff --git a/src/user/srv.init/loader.cpp b/src/user/srv.init/loader.cpp index bbb22c5..8cd2a16 100644 --- a/src/user/srv.init/loader.cpp +++ b/src/user/srv.init/loader.cpp @@ -192,10 +192,10 @@ give_handle(j6_handle_t proc, j6_handle_t h, const char *name) } static j6_handle_t -create_process(j6_handle_t sys, j6_handle_t slp, j6_handle_t vfs) +create_process(j6_handle_t sys, j6_handle_t slp, j6_handle_t vfs, const char *path) { j6_handle_t proc = j6_handle_invalid; - j6_status_t res = j6_process_create(&proc); + j6_status_t res = j6_process_create(&proc, path); if (res != j6_status_ok) { j6::syslog(j6::logs::srv, j6::log_level::error, "error loading program: creating process: %lx", res); return j6_handle_invalid; @@ -231,7 +231,7 @@ load_program( const module *arg) { j6::syslog(j6::logs::srv, j6::log_level::info, "Loading program '%s' into new process", path); - j6_handle_t proc = create_process(sys, slp, vfs); + j6_handle_t proc = create_process(sys, slp, vfs, path); if (proc == j6_handle_invalid) return false;