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.
This commit is contained in:
2026-06-06 17:25:00 +01:00
parent c90ee285cc
commit 4d30949a4d
13 changed files with 485 additions and 1 deletions
+4
View File
@@ -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)
+29
View File
@@ -0,0 +1,29 @@
#include <magenta/debug/event.h>
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 "<unknown>";
}
}
+110
View File
@@ -0,0 +1,110 @@
#include "magenta/debug/util.h"
#include <magenta/debug/host.h>
#include <magenta/debug/packet.h>
#include <magenta/debug/request.h>
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;
}
+23
View File
@@ -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
+61
View File
@@ -0,0 +1,61 @@
#ifndef MAGENTA_DEBUG_HOST_H_
#define MAGENTA_DEBUG_HOST_H_
#include <magenta/debug/identity.h>
#include <magenta/debug/status.h>
#include <stddef.h>
#include <stdint.h>
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
+16
View File
@@ -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
+66
View File
@@ -0,0 +1,66 @@
#ifndef MAGENTA_DEBUG_PACKET_H_
#define MAGENTA_DEBUG_PACKET_H_
#include <magenta/debug/event.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#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
+11
View File
@@ -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
+12
View File
@@ -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
+14
View File
@@ -0,0 +1,14 @@
#ifndef MAGENTA_DEBUG_UTIL_H_
#define MAGENTA_DEBUG_UTIL_H_
#if defined(KERNEL_VERSION)
#include <kernel/libc/string.h>
#include <kernel/printk.h>
#define debug_printf(...) printk(__VA_ARGS__)
#else
#include <stdio.h>
#include <string.h>
#define debug_printf(...) printf(__VA_ARGS__)
#endif
#endif
+20
View File
@@ -0,0 +1,20 @@
#include <magenta/debug/packet.h>
#include <magenta/debug/util.h>
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;
}
+106
View File
@@ -0,0 +1,106 @@
#include <magenta/debug/host.h>
#include <magenta/debug/packet.h>
#include <magenta/debug/util.h>
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;
}