From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7524 invoked by alias); 18 Jan 2019 10:50:12 -0000 Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org Received: (qmail 7053 invoked by uid 89); 18 Jan 2019 10:50:11 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-0.9 required=5.0 tests=BAYES_00,KAM_LAZY_DOMAIN_SECURITY autolearn=no version=3.3.2 spammy=H*r:sk:gdb@sou, Hx-languages-length:4610, symtab, H*r:4.84_2 X-HELO: mailout5.zih.tu-dresden.de Received: from mailout5.zih.tu-dresden.de (HELO mailout5.zih.tu-dresden.de) (141.30.67.74) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 18 Jan 2019 10:50:09 +0000 Received: from mail.zih.tu-dresden.de ([141.76.14.4]) by mailout5.zih.tu-dresden.de with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.84_2) (envelope-from ) id 1gkRiv-0005EW-R3 for gdb@sourceware.org; Fri, 18 Jan 2019 11:50:06 +0100 Received: from [155.56.40.47] (helo=archvm) by server-50.mailclusterdns.zih.tu-dresden.de with esmtpsa (TLSv1.2:AES256-SHA:256) (envelope-from ) id 1gkRiv-0007Ee-ND for gdb@sourceware.org; Fri, 18 Jan 2019 11:50:05 +0100 Date: Fri, 18 Jan 2019 10:50:00 -0000 From: Frank Tetzel To: gdb@sourceware.org Subject: jit interface and jit reader Message-ID: <20190118115004.1a51eefc@archvm> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="MP_/KEMQttgJwS/OAcz6LqM3S=p" X-TUD-Original-From: frank.tetzel@tu-dresden.de X-IsSubscribed: yes X-SW-Source: 2019-01/txt/msg00011.txt.bz2 --MP_/KEMQttgJwS/OAcz6LqM3S=p Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 870 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 --MP_/KEMQttgJwS/OAcz6LqM3S=p Content-Type: text/x-c++src Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=gdbjit.cpp Content-length: 2029 #include #include #include #include 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(); } --MP_/KEMQttgJwS/OAcz6LqM3S=p Content-Type: text/x-c++src Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=gdbjit-reader.c Content-length: 1752 #include #include #include 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; } --MP_/KEMQttgJwS/OAcz6LqM3S=p--