This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

jit interface and jit reader


Hi,

I have trouble getting GDB's jit interface to work. I'm trying to make
application using AsmJit [1] easier to debug by being able to break
when entering jitted code. As AsmJit is just an assembler returning a
function pointer to the generated code, I do not want to create an
object file for it. That is why I'm trying to use jit-reader, but the
symbol does not seem to show up in GDB and a pending breakpoint is
never hit.

What am I doing wrong? I attached two files: gdbjit.cpp is talking to
GDB via the jit interface. gdbjit-reader.c is the jit reader for GDB
which I compile to a shared object and load in GDB with jit-reader-load.

It does not implement unwind and get_frame_id. Do I need these
functions? unwind is called sometimes. Is there a minimal example
somewhere which implements jit reader?

Best regards,
Frank

[1] https://github.com/asmjit/asmjit
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cstdint>


extern "C" {

typedef enum {
	JIT_NOACTION = 0,
	JIT_REGISTER_FN,
	JIT_UNREGISTER_FN,
} jit_actions_t;

struct jit_code_entry {
	struct jit_code_entry *next_entry;
	struct jit_code_entry *prev_entry;
	const char *symfile_addr;
	uint64_t symfile_size;
};

struct jit_descriptor {
	uint32_t version;
	// This type should be jit_actions_t, but we use uint32_t
	// to be explicit about the bitwidth.
	uint32_t action_flag;
	struct jit_code_entry *relevant_entry;
	struct jit_code_entry *first_entry;
};

// GDB puts a breakpoint in this function.
void __attribute__((noinline)) __jit_debug_register_code() {}

// Make sure to specify the version statically, because the
// debugger may check the version before we can set it.
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };

} // extern "C"


void register_code(const char *name, uint64_t addr, uint64_t size){
	puts("register_code called");
	printf("name: %s; addr: %lu; size: %lu\n", name, addr, size);

	uint64_t name_size = strlen(name)+1; // including null terminator
	uint64_t symfile_size = name_size + 2*sizeof(uint64_t);
	char *symfile = (char*)malloc(symfile_size);
	char *ptr = symfile;
	// begin address
	*(uint64_t*)ptr = addr;
	ptr += sizeof(uint64_t);
	// end address
	*(uint64_t*)ptr = addr + size;
	ptr += sizeof(uint64_t);
	// function/symbol name
	(void)memcpy(ptr, name, name_size);

	// create entry
	jit_code_entry *n = new jit_code_entry; //FIXME: memory leak currently
	n->next_entry = nullptr;
	n->prev_entry = nullptr;
	n->symfile_addr = symfile;
	n->symfile_size = symfile_size;
	// insert into linked list
	jit_code_entry *entry = __jit_debug_descriptor.first_entry;
	n->next_entry = entry;
	if(entry){
		entry->prev_entry = n;
	}
	__jit_debug_descriptor.first_entry = n;
	// let GDB know about the new entry
	__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
	__jit_debug_descriptor.relevant_entry = n;

	puts("calling GDB");
	__jit_debug_register_code();
}
#include <gdb/jit-reader.h>

#include <stdlib.h>
#include <stdio.h>


GDB_DECLARE_GPL_COMPATIBLE_READER




enum gdb_status read_debug_info(struct gdb_reader_funcs *self, struct gdb_symbol_callbacks *cb, void *memory, long memory_sz){
	puts("reader read_debug_info called");

	// get begin and end of code segment
	GDB_CORE_ADDR begin = *(GDB_CORE_ADDR*)memory;
	memory += sizeof(GDB_CORE_ADDR);
	GDB_CORE_ADDR end = *(GDB_CORE_ADDR*)memory;
	memory += sizeof(GDB_CORE_ADDR);
	// get name of function, just a single one per file
	const char *name = (const char*)memory;

	printf("creating symbol %s at %lu - %lu (size=%lu)\n", name, begin, end, end - begin);

	struct gdb_object *obj = cb->object_open(cb);
	struct gdb_symtab *symtab = cb->symtab_open(cb, obj, NULL);
	struct gdb_block *block = cb->block_open(cb, symtab, NULL, begin, end, name);

	cb->symtab_close(cb, symtab);
	cb->object_close(cb, obj);
	return GDB_SUCCESS;
}

enum gdb_status unwind(struct gdb_reader_funcs *self, struct gdb_unwind_callbacks *cb){
	puts("reader unwind called");

	//TODO
	return GDB_FAIL;
}

struct gdb_frame_id get_frame_id(struct gdb_reader_funcs *self, struct gdb_unwind_callbacks *cb){
	puts("reader get_frame_id called");

	//TODO
	struct gdb_frame_id frame = {0, 0};
	return frame;
}

void destroy(struct gdb_reader_funcs *self){
	puts("reader destroy called");

	free(self);
}


struct gdb_reader_funcs *gdb_init_reader(void){
	puts("gdb_init_reader called");

	struct gdb_reader_funcs *funcs = malloc(sizeof(struct gdb_reader_funcs));
	funcs->reader_version = GDB_READER_INTERFACE_VERSION;
	funcs->priv_data = NULL;

	funcs->read = read_debug_info;
	funcs->unwind = unwind;
	funcs->get_frame_id = get_frame_id;
	funcs->destroy = destroy;

	return funcs;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]