[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.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <j6/memutils.h>
|
||||
#include <util/no_construct.h>
|
||||
|
||||
#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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <typename T> 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<uintptr_t>(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<uint64_t*>(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<uint64_t*>(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() : "<Unknown>";
|
||||
|
||||
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 <typename T> inline bool
|
||||
canonical(T p)
|
||||
{
|
||||
static constexpr uintptr_t mask = 0xffff800000000000;
|
||||
uintptr_t addr = reinterpret_cast<uintptr_t>(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) : "<END>";
|
||||
if (!name)
|
||||
name = canonical(fp->return_addr) ? "<unknown>" : "<corrupt>";
|
||||
name = check_pointer(fp->return_addr) ? "<unknown>" : "<unmapped>";
|
||||
|
||||
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 ? " <inaccessible>" : "";
|
||||
util::format({message, sizeof(message)}, " \e[0mfinal <0x%016lx>%s\n",
|
||||
fp, result);
|
||||
out.write(message);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -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<process>(self);
|
||||
process *p = construct_handle<process>(self, path);
|
||||
log::info(logs::task, "Process <%02lx> created", p->obj_id());
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
@@ -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<logs>(area), static_cast<log::level>(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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user