Skip to content

Instantly share code, notes, and snippets.

@no-defun-allowed
Created December 31, 2025 15:53
Show Gist options
  • Select an option

  • Save no-defun-allowed/32d38c5e664586c724cf2e0e97f0d2b1 to your computer and use it in GitHub Desktop.

Select an option

Save no-defun-allowed/32d38c5e664586c724cf2e0e97f0d2b1 to your computer and use it in GitHub Desktop.
#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(&reg, 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