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; +}