From 4d30949a4dea85518c77ecadb4e3d0dca481ff38 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sat, 6 Jun 2026 17:25:00 +0100 Subject: [PATCH] meta: add debugging library the debug library can be used by both server (the kernel) and client (the debugger) applications. the library implements the protocol that is used for communication between the kernel and debugger, as well as handling for any requests supported by the protocol. --- CMakeLists.txt | 14 +++- debug/CMakeLists.txt | 4 + debug/event.c | 29 +++++++ debug/host.c | 110 +++++++++++++++++++++++++ debug/include/magenta/debug/event.h | 23 ++++++ debug/include/magenta/debug/host.h | 61 ++++++++++++++ debug/include/magenta/debug/identity.h | 16 ++++ debug/include/magenta/debug/packet.h | 66 +++++++++++++++ debug/include/magenta/debug/request.h | 11 +++ debug/include/magenta/debug/status.h | 12 +++ debug/include/magenta/debug/util.h | 14 ++++ debug/packet.c | 20 +++++ debug/request.c | 106 ++++++++++++++++++++++++ 13 files changed, 485 insertions(+), 1 deletion(-) create mode 100644 debug/CMakeLists.txt create mode 100644 debug/event.c create mode 100644 debug/host.c create mode 100644 debug/include/magenta/debug/event.h create mode 100644 debug/include/magenta/debug/host.h create mode 100644 debug/include/magenta/debug/identity.h create mode 100644 debug/include/magenta/debug/packet.h create mode 100644 debug/include/magenta/debug/request.h create mode 100644 debug/include/magenta/debug/status.h create mode 100644 debug/include/magenta/debug/util.h create mode 100644 debug/packet.c create mode 100644 debug/request.c diff --git a/CMakeLists.txt b/CMakeLists.txt index fe51f1c..cabcb47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,7 +69,19 @@ add_custom_command( COMMAND ${CMAKE_STRIP} -g $) target_link_libraries(${kernel_exe_name} -nostdlib -ffreestanding -lgcc) -target_compile_definitions(${kernel_exe_name} PRIVATE KERNEL_VERSION="${kernel_version}") +target_compile_definitions(${kernel_exe_name} PRIVATE + KERNEL_NAME="${kernel_name}" + KERNEL_VERSION="${kernel_version}" + KERNEL_ARCH="${kernel_arch}") include(arch/${kernel_arch}/config.cmake) include(arch/${kernel_arch}/targets.cmake) + +add_subdirectory(debug) +target_link_libraries(${kernel_exe_name} magenta_debug) +target_compile_definitions(magenta_debug PRIVATE KERNEL_VERSION="${kernel_version}") +target_include_directories(magenta_debug PRIVATE + include + libc/include + libmagenta/include + arch/${kernel_arch}/include) diff --git a/debug/CMakeLists.txt b/debug/CMakeLists.txt new file mode 100644 index 0000000..03a2e96 --- /dev/null +++ b/debug/CMakeLists.txt @@ -0,0 +1,4 @@ +file(GLOB sources *.c *.h include/magenta/debug/*.h) + +add_library(magenta_debug STATIC ${sources}) +target_include_directories(magenta_debug PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/debug/event.c b/debug/event.c new file mode 100644 index 0000000..f4a58d7 --- /dev/null +++ b/debug/event.c @@ -0,0 +1,29 @@ +#include + +const char *mxdbg_event_type_get_description(enum mxdbg_event_type type) +{ + switch (type) { + case MXDBG_EVENT_TASK_CREATED: + return "task-create"; + case MXDBG_EVENT_TASK_STARTED: + return "task-start"; + case MXDBG_EVENT_TASK_STOPPED: + return "task-stop"; + case MXDBG_EVENT_TASK_DESTROYED: + return "task-destroy"; + case MXDBG_EVENT_THREAD_CREATED: + return "thread-create"; + case MXDBG_EVENT_THREAD_STARTED: + return "thread-start"; + case MXDBG_EVENT_THREAD_STOPPED: + return "thread-stop"; + case MXDBG_EVENT_THREAD_DESTROYED: + return "thread-destroy"; + case MXDBG_EVENT_THREAD_FAULT: + return "thread-fault"; + case MXDBG_EVENT_PANIC: + return "panic"; + default: + return ""; + } +} diff --git a/debug/host.c b/debug/host.c new file mode 100644 index 0000000..f3cbbf5 --- /dev/null +++ b/debug/host.c @@ -0,0 +1,110 @@ +#include "magenta/debug/util.h" + +#include +#include +#include + +enum mxdbg_status mxdbg_host_handle_request(struct mxdbg_host *host) +{ + struct mxdbg_packet packet = {0}; + enum mxdbg_status status = mxdbg_host_recv(host, &packet); + if (status != MXDBG_SUCCESS) { + debug_printf("debug: failed to read packet"); + return status; + } + + if (packet.pkt_magic != MXDBG_PACKET_MAGIC) { + debug_printf( + "debug: packet is malformed (magic=%08x)", + packet.pkt_magic); + return MXDBG_ERR_BAD_FORMAT; + } + + return mxdbg_handle_request(host, &packet); +} + +enum mxdbg_status mxdbg_host_recv( + struct mxdbg_host *host, + struct mxdbg_packet *packet) +{ + size_t r; + + if (host->read_remote) { + return host->read_remote(host, packet, sizeof *packet, &r); + } + + return MXDBG_ERR_NOT_SUPPORTED; +} + +enum mxdbg_status mxdbg_host_recv_packet_data( + struct mxdbg_host *host, + struct mxdbg_packet *packet) +{ + if (packet->pkt_magic != MXDBG_PACKET_MAGIC) { + return MXDBG_ERR_INVALID_ARGUMENT; + } + + if (!packet->pkt_length) { + return MXDBG_SUCCESS; + } + + size_t r; + void *dest = packet + 1; + if (host->read_remote) { + return host->read_remote( + host, + dest, + packet->pkt_length - sizeof *packet, + &r); + } + + return MXDBG_ERR_NOT_SUPPORTED; +} + +enum mxdbg_status mxdbg_host_send( + struct mxdbg_host *host, + const struct mxdbg_packet *packet) +{ + size_t w; + if (host->write_remote) { + return host->write_remote(host, packet, packet->pkt_length, &w); + } + + return MXDBG_ERR_NOT_SUPPORTED; +} + +enum mxdbg_status mxdbg_host_identify( + struct mxdbg_host *host, + enum mxdbg_identity_key key, + void *out, + size_t max) +{ + if (host->identify) { + return host->identify(host, key, out, max); + } + + return MXDBG_ERR_NOT_SUPPORTED; +} + +enum mxdbg_status mxdbg_host_identify_task( + struct mxdbg_host *host, + unsigned int tid, + enum mxdbg_identity_key key, + void *out, + size_t max) +{ + if (host->identify_task) { + return host->identify_task(host, tid, key, out, max); + } + + return MXDBG_ERR_NOT_SUPPORTED; +} + +enum mxdbg_status mxdbg_host_resume(struct mxdbg_host *host) +{ + if (host->resume) { + return host->resume(host); + } + + return MXDBG_ERR_NOT_SUPPORTED; +} diff --git a/debug/include/magenta/debug/event.h b/debug/include/magenta/debug/event.h new file mode 100644 index 0000000..a9a2210 --- /dev/null +++ b/debug/include/magenta/debug/event.h @@ -0,0 +1,23 @@ +#ifndef MAGENTA_DEBUG_EVENT_H_ +#define MAGENTA_DEBUG_EVENT_H_ + +enum mxdbg_event_type { + MXDBG_EVENT_NONE = 0, + + MXDBG_EVENT_TASK_CREATED, + MXDBG_EVENT_TASK_STARTED, + MXDBG_EVENT_TASK_STOPPED, + MXDBG_EVENT_TASK_DESTROYED, + + MXDBG_EVENT_THREAD_CREATED, + MXDBG_EVENT_THREAD_STARTED, + MXDBG_EVENT_THREAD_STOPPED, + MXDBG_EVENT_THREAD_DESTROYED, + MXDBG_EVENT_THREAD_FAULT, + + MXDBG_EVENT_PANIC, +}; + +extern const char *mxdbg_event_type_get_description(enum mxdbg_event_type type); + +#endif diff --git a/debug/include/magenta/debug/host.h b/debug/include/magenta/debug/host.h new file mode 100644 index 0000000..a3b3488 --- /dev/null +++ b/debug/include/magenta/debug/host.h @@ -0,0 +1,61 @@ +#ifndef MAGENTA_DEBUG_HOST_H_ +#define MAGENTA_DEBUG_HOST_H_ + +#include +#include +#include +#include + +struct mxdbg_packet; +struct mxdbg_packet_event; + +struct mxdbg_host { + enum mxdbg_status ( + *read_remote)(struct mxdbg_host *, void *, size_t, size_t *); + enum mxdbg_status (*write_remote)( + struct mxdbg_host *, + const void *, + size_t, + size_t *); + enum mxdbg_status (*identify)( + struct mxdbg_host *, + enum mxdbg_identity_key, + void *, + size_t); + enum mxdbg_status (*identify_task)( + struct mxdbg_host *, + unsigned int, + enum mxdbg_identity_key, + void *, + size_t); + enum mxdbg_status (*resume)(struct mxdbg_host *); +}; + +extern enum mxdbg_status mxdbg_host_handle_request(struct mxdbg_host *host); + +extern enum mxdbg_status mxdbg_host_recv( + struct mxdbg_host *host, + struct mxdbg_packet *packet); +extern enum mxdbg_status mxdbg_host_recv_packet_data( + struct mxdbg_host *host, + struct mxdbg_packet *packet); +extern enum mxdbg_status mxdbg_host_send( + struct mxdbg_host *host, + const struct mxdbg_packet *packet); +extern enum mxdbg_status mxdbg_host_identify( + struct mxdbg_host *host, + enum mxdbg_identity_key key, + void *out, + size_t max); +extern enum mxdbg_status mxdbg_host_identify_task( + struct mxdbg_host *host, + unsigned int task, + enum mxdbg_identity_key key, + void *out, + size_t max); +extern enum mxdbg_status mxdbg_host_resume(struct mxdbg_host *host); +extern enum mxdbg_status mxdbg_host_send_event( + struct mxdbg_host *host, + struct mxdbg_packet_event *ev); + +#endif diff --git a/debug/include/magenta/debug/identity.h b/debug/include/magenta/debug/identity.h new file mode 100644 index 0000000..89d66e7 --- /dev/null +++ b/debug/include/magenta/debug/identity.h @@ -0,0 +1,16 @@ +#ifndef MAGENTA_DEBUG_IDENTITY_H_ +#define MAGENTA_DEBUG_IDENTITY_H_ + +enum mxdbg_identity_key { + MXDBG_IDENTITY_NONE = 0, + MXDBG_IDENTITY_KERNEL_NAME, + MXDBG_IDENTITY_KERNEL_VERSION, + MXDBG_IDENTITY_KERNEL_ARCH, + + /* identify_task keys */ + MXDBG_IDENTITY_TASK_NAME, + MXDBG_IDENTITY_TASK_PARENT, + MXDBG_IDENTITY_TASK_NR_THREADS, +}; + +#endif diff --git a/debug/include/magenta/debug/packet.h b/debug/include/magenta/debug/packet.h new file mode 100644 index 0000000..3f850fa --- /dev/null +++ b/debug/include/magenta/debug/packet.h @@ -0,0 +1,66 @@ +#ifndef MAGENTA_DEBUG_PACKET_H_ +#define MAGENTA_DEBUG_PACKET_H_ + +#include +#include +#include +#include + +#define MXDBG_PACKET_MAGIC 0xdecafbaf + +enum mxdbg_packet_type { + MXDBG_PACKET_NONE = 0, + MXDBG_PACKET_IDENTIFY_KERNEL, + MXDBG_PACKET_IDENTIFY_TASK, + MXDBG_PACKET_LIST_TASK, + MXDBG_PACKET_RESUME, + MXDBG_PACKET_STOP, + MXDBG_PACKET_EVENT, +}; + +enum mxdbg_packet_flags { + MXDBG_PACKET_F_NONE = 0, + MXDBG_PACKET_F_RESPONSE = 0x01u, +}; + +struct mxdbg_packet { + uint32_t pkt_magic; + uint16_t pkt_length; + uint8_t pkt_type; + uint8_t pkt_flags; +}; + +struct mxdbg_packet_identify_kernel { + struct mxdbg_packet id_base; + char id_kernel_name[32]; + char id_kernel_version[32]; + char id_kernel_arch[16]; +}; + +struct mxdbg_packet_list_task { + struct mxdbg_packet l_base; + uint16_t l_task_count; +}; + +struct mxdbg_packet_identify_task { + struct mxdbg_packet id_base; + uint16_t id_task, id_parent; + uint16_t id_thread_count; + char id_task_name[64]; +}; + +struct mxdbg_packet_event { + struct mxdbg_packet ev_base; + uint16_t ev_type; + uint16_t ev_task, ev_thread; + uint32_t ev_code; +}; + +extern void mxdbg_packet_init( + struct mxdbg_packet *packet, + size_t size, + enum mxdbg_packet_type type, + enum mxdbg_packet_flags flags); +extern bool mxdbg_packet_validate(const struct mxdbg_packet *packet); + +#endif diff --git a/debug/include/magenta/debug/request.h b/debug/include/magenta/debug/request.h new file mode 100644 index 0000000..86326ef --- /dev/null +++ b/debug/include/magenta/debug/request.h @@ -0,0 +1,11 @@ +#ifndef MAGENTA_DEBUG_REQUEST_H_ +#define MAGENTA_DEBUG_REQUEST_H_ + +struct mxdbg_host; +struct mxdbg_packet; + +extern enum mxdbg_status mxdbg_handle_request( + struct mxdbg_host *host, + const struct mxdbg_packet *req); + +#endif diff --git a/debug/include/magenta/debug/status.h b/debug/include/magenta/debug/status.h new file mode 100644 index 0000000..731ef81 --- /dev/null +++ b/debug/include/magenta/debug/status.h @@ -0,0 +1,12 @@ +#ifndef MAGENTA_DEBUG_STATUS_H_ +#define MAGENTA_DEBUG_STATUS_H_ + +enum mxdbg_status { + MXDBG_SUCCESS = 0, + MXDBG_ERR_INVALID_ARGUMENT, + MXDBG_ERR_NOT_SUPPORTED, + MXDBG_ERR_BAD_FORMAT, + MXDBG_ERR_IO_FAILURE, +}; + +#endif diff --git a/debug/include/magenta/debug/util.h b/debug/include/magenta/debug/util.h new file mode 100644 index 0000000..3a5267d --- /dev/null +++ b/debug/include/magenta/debug/util.h @@ -0,0 +1,14 @@ +#ifndef MAGENTA_DEBUG_UTIL_H_ +#define MAGENTA_DEBUG_UTIL_H_ + +#if defined(KERNEL_VERSION) +#include +#include +#define debug_printf(...) printk(__VA_ARGS__) +#else +#include +#include +#define debug_printf(...) printf(__VA_ARGS__) +#endif + +#endif diff --git a/debug/packet.c b/debug/packet.c new file mode 100644 index 0000000..a06800c --- /dev/null +++ b/debug/packet.c @@ -0,0 +1,20 @@ +#include +#include + +void mxdbg_packet_init( + struct mxdbg_packet *packet, + size_t size, + enum mxdbg_packet_type type, + enum mxdbg_packet_flags flags) +{ + memset(packet, 0x0, sizeof *packet); + packet->pkt_magic = MXDBG_PACKET_MAGIC; + packet->pkt_length = size; + packet->pkt_type = type; + packet->pkt_flags = flags; +} + +bool mxdbg_packet_validate(const struct mxdbg_packet *packet) +{ + return packet->pkt_magic == MXDBG_PACKET_MAGIC; +} diff --git a/debug/request.c b/debug/request.c new file mode 100644 index 0000000..bc7e0f2 --- /dev/null +++ b/debug/request.c @@ -0,0 +1,106 @@ +#include +#include +#include + +static enum mxdbg_status identify_kernel( + struct mxdbg_host *host, + const struct mxdbg_packet *req) +{ + struct mxdbg_packet_identify_kernel id = {0}; + mxdbg_packet_init( + &id.id_base, + sizeof id, + MXDBG_PACKET_IDENTIFY_KERNEL, + MXDBG_PACKET_F_RESPONSE); + + mxdbg_host_identify( + host, + MXDBG_IDENTITY_KERNEL_NAME, + id.id_kernel_name, + sizeof id.id_kernel_name); + mxdbg_host_identify( + host, + MXDBG_IDENTITY_KERNEL_VERSION, + id.id_kernel_version, + sizeof id.id_kernel_version); + mxdbg_host_identify( + host, + MXDBG_IDENTITY_KERNEL_ARCH, + id.id_kernel_arch, + sizeof id.id_kernel_arch); + + mxdbg_host_send(host, &id.id_base); + + return MXDBG_SUCCESS; +} + +static enum mxdbg_status identify_task( + struct mxdbg_host *host, + const struct mxdbg_packet *packet) +{ + struct mxdbg_packet_identify_task *req + = (struct mxdbg_packet_identify_task *)packet; + struct mxdbg_packet_identify_task id = {0}; + id.id_base = *packet; + mxdbg_host_recv_packet_data(host, &id.id_base); + unsigned int tid = id.id_task; + + mxdbg_packet_init( + &id.id_base, + sizeof id, + MXDBG_PACKET_IDENTIFY_TASK, + MXDBG_PACKET_F_RESPONSE); + + mxdbg_host_identify_task( + host, + tid, + MXDBG_IDENTITY_TASK_NAME, + id.id_task_name, + sizeof id.id_task_name); + mxdbg_host_identify_task( + host, + tid, + MXDBG_IDENTITY_TASK_PARENT, + &id.id_parent, + sizeof id.id_parent); + mxdbg_host_identify_task( + host, + tid, + MXDBG_IDENTITY_TASK_NR_THREADS, + &id.id_thread_count, + sizeof id.id_thread_count); + + size_t w; + mxdbg_host_send(host, &id.id_base); + debug_printf("debug: identify_task response sent"); + + return MXDBG_SUCCESS; +} + +static enum mxdbg_status resume( + struct mxdbg_host *host, + const struct mxdbg_packet *req) +{ + return mxdbg_host_resume(host); +} + +enum mxdbg_status mxdbg_handle_request( + struct mxdbg_host *host, + const struct mxdbg_packet *req) +{ + switch (req->pkt_type) { + case MXDBG_PACKET_IDENTIFY_KERNEL: + return identify_kernel(host, req); + case MXDBG_PACKET_IDENTIFY_TASK: + return identify_task(host, req); + case MXDBG_PACKET_RESUME: + return resume(host, req); + default: + debug_printf( + "debug: unrecognised packet 0x%02x", + req->pkt_type); + return MXDBG_ERR_NOT_SUPPORTED; + } + + return MXDBG_SUCCESS; +}