From 6e0f32f4ca4b35bda036caa6ad3abcae4ae64cdc Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 18 Dec 2024 05:01:33 +0800 Subject: Added initial GDBJIT support (#2162) * Added GDBJIT support * fix * fix --- src/tools/gdbjit.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/tools/gdbjit.c (limited to 'src/tools') diff --git a/src/tools/gdbjit.c b/src/tools/gdbjit.c new file mode 100644 index 00000000..d91c4c05 --- /dev/null +++ b/src/tools/gdbjit.c @@ -0,0 +1,134 @@ +#ifdef GDBJIT +#include +#include +#include +#include +#include +#include "gdbjit.h" +#include "dynablock.h" +#include "debug.h" + + +/* GDB JIT Compilation Interface ----------------------------------------------- + * https://sourceware.org/gdb/current/onlinedocs/gdb.html/JIT-Interface.html + */ + +enum { + GDBJIT_NOACTION = 0, + GDBJIT_REGISTER, + GDBJIT_UNREGISTER +}; + +typedef struct gdbjit_code_entry_s { + struct gdbjit_code_entry_s* next_entry; + struct gdbjit_code_entry_s* prev_entry; + const char* symfile_addr; + uint64_t symfile_size; +} gdbjit_code_entry_t; + +typedef struct gdbjit_descriptor_s { + uint32_t version; + uint32_t action_flag; + gdbjit_code_entry_t* relevant_entry; + gdbjit_code_entry_t* first_entry; +} gdbjit_descriptor_t; + +/* GDB puts a breakpoint in this function. This can't be optimized out. */ +void __attribute__((noinline)) __jit_debug_register_code() +{ + asm volatile("" ::: "memory"); +}; + +/* Make sure to specify the version statically, because the debugger may check + * the version before we can set it. + */ +gdbjit_descriptor_t __jit_debug_descriptor = { 1, GDBJIT_NOACTION, NULL, NULL }; + +/* --------------------------------------------------------------------------- */ + +void GdbJITNewBlock(gdbjit_block_t* block, GDB_CORE_ADDR start, GDB_CORE_ADDR end) +{ + if (!block) + return; + + memset(block, 0, sizeof(gdbjit_block_t)); + + strcpy(block->filename, "/tmp/box64gdbjit-XXXXXX.S"); + int fd = mkstemps(block->filename, 2); + block->file = fdopen(fd, "w"); + + block->start = start; + block->end = end; + block->alloced = block->nlines = 0; +} + +static size_t GdbJITLinesAvailable(gdbjit_block_t* block) +{ + if (!block) + return 0; + + return block->alloced > block->nlines; +} + +#define GDBJIT_LINES_MAX_PREALLOC 64 + +static gdbjit_block_t* GdbJITMakeRoom(gdbjit_block_t* block) +{ + if (!block) return NULL; + + if (!GdbJITLinesAvailable(block)) { + size_t new_size = block->alloced + GDBJIT_LINES_MAX_PREALLOC; + block = box_realloc(block, sizeof(gdbjit_block_t) + new_size * sizeof(struct gdb_line_mapping)); + if (!block) return NULL; + block->alloced = new_size; + } + return block; +} + +gdbjit_block_t* GdbJITBlockAddLine(gdbjit_block_t* block, GDB_CORE_ADDR addr, const char* line) +{ + block->nlines++; + block = GdbJITMakeRoom(block); + if (!block) return NULL; + + block->lines[block->nlines-1].pc = addr; + block->lines[block->nlines-1].line = block->nlines; + fprintf(block->file, "%s\n", line); + fflush(block->file); + return block; +} + +void GdbJITBlockReady(gdbjit_block_t* block) +{ + if (!block) return; + + if (block->nlines == 0) { + fclose(block->file); + box_free(block); + return; + } + + gdbjit_code_entry_t* entry = (gdbjit_code_entry_t*)box_malloc(sizeof(gdbjit_code_entry_t)); + if (!entry) { + fclose(block->file); + box_free(block); + return; + } + + fclose(block->file); + + entry->symfile_addr = (const char*)block; + entry->symfile_size = sizeof(gdbjit_block_t) + block->nlines * sizeof(struct gdb_line_mapping); + + if (__jit_debug_descriptor.first_entry) { + __jit_debug_descriptor.relevant_entry->next_entry = entry; + entry->prev_entry = __jit_debug_descriptor.relevant_entry; + } else { + __jit_debug_descriptor.first_entry = entry; + } + + __jit_debug_descriptor.relevant_entry = entry; + __jit_debug_descriptor.action_flag = GDBJIT_REGISTER; + __jit_debug_register_code(); +} +#endif -- cgit 1.4.1