Created
December 31, 2025 15:53
-
-
Save no-defun-allowed/32d38c5e664586c724cf2e0e97f0d2b1 to your computer and use it in GitHub Desktop.
https://github.com/no-defun-allowed/ccl/blob/master/lisp-kernel/gdb.c GDB plugin thingy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <gdb/jit-reader.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| GDB_DECLARE_GPL_COMPATIBLE_READER; | |
| static enum gdb_status read_debug_info(struct gdb_reader_funcs *self, struct gdb_symbol_callbacks *cbs, void *memory, long bytes) { | |
| fprintf(stderr, "time to read %ld bytes\n", bytes); | |
| char *mem = (char*)memory, *mem_end = (char*)memory + bytes; | |
| struct gdb_object *object = cbs->object_open(cbs); | |
| struct gdb_symtab *symtab = cbs->symtab_open(cbs, object, "ccl"); | |
| int count = 0; | |
| GDB_CORE_ADDR bottom = -1, top = 0; | |
| while (mem < mem_end) { | |
| char name[128]; | |
| GDB_CORE_ADDR begin, end; | |
| begin = *(GDB_CORE_ADDR*)mem; mem += sizeof(GDB_CORE_ADDR); | |
| if (end > top) top = end; | |
| if (begin < bottom) bottom = begin; | |
| end = *(GDB_CORE_ADDR*)mem; mem += sizeof(GDB_CORE_ADDR); | |
| strncpy(name, mem, 128); | |
| /* Skip over the string */ | |
| mem += strlen(mem) + 1; | |
| cbs->block_open(cbs, symtab, NULL, begin, end, name); | |
| count++; | |
| } | |
| cbs->symtab_close(cbs, symtab); | |
| cbs->object_close(cbs, object); | |
| if (mem > mem_end) { | |
| fprintf(stderr, "fell off end, %ld bytes of %ld\n", mem - (char*)memory, bytes); | |
| return GDB_FAIL; | |
| } else { | |
| fprintf(stderr, "read %d Lisp symbols in %lx...%lx\n", count, bottom, top); | |
| return GDB_SUCCESS; | |
| } | |
| } | |
| static GDB_CORE_ADDR read_register(struct gdb_unwind_callbacks *cbs, int n) { | |
| struct gdb_reg_value *value = cbs->reg_get(cbs, n); | |
| GDB_CORE_ADDR reg; | |
| memcpy(®, value->value, 8); | |
| value->free(value); | |
| return reg; | |
| } | |
| static void write_register(struct gdb_unwind_callbacks *cbs, int n, GDB_CORE_ADDR v) { | |
| /* gdb_reg_value has room for one byte of value[], we want a word */ | |
| struct gdb_reg_value *value = malloc(sizeof(struct gdb_reg_value) + sizeof(GDB_CORE_ADDR) - 1); | |
| value->defined = 1; | |
| value->free = free; | |
| memcpy(&value->value, &v, 8); | |
| cbs->reg_set(cbs, n, value); | |
| } | |
| static GDB_CORE_ADDR read_word(struct gdb_unwind_callbacks *cbs, GDB_CORE_ADDR addr) { | |
| GDB_CORE_ADDR word; | |
| cbs->target_read(addr, &word, sizeof(GDB_CORE_ADDR)); | |
| return word; | |
| } | |
| #define RIP 16 | |
| #define RBP 6 | |
| static enum gdb_status unwind_frame(struct gdb_reader_funcs* self, struct gdb_unwind_callbacks* cbs) { | |
| GDB_CORE_ADDR bp = read_register(cbs, RBP); | |
| GDB_CORE_ADDR old_bp = read_word(cbs, bp), old_rip = read_word(cbs, bp + 8); | |
| write_register(cbs, RBP, old_bp); | |
| write_register(cbs, RIP, old_rip); | |
| return GDB_SUCCESS; | |
| } | |
| static struct gdb_frame_id get_frame_id(struct gdb_reader_funcs* self, struct gdb_unwind_callbacks* cbs) { | |
| GDB_CORE_ADDR pc = read_register(cbs, RIP), sp = read_register(cbs, RBP); | |
| struct gdb_frame_id frame = {pc, sp}; | |
| return frame; | |
| } | |
| static void destroy_reader(struct gdb_reader_funcs* self) { } | |
| static struct gdb_reader_funcs reader = {GDB_READER_INTERFACE_VERSION, NULL, read_debug_info, unwind_frame, get_frame_id, destroy_reader}; | |
| struct gdb_reader_funcs* gdb_init_reader(void) { return &reader; } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment