From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25792 invoked by alias); 9 Aug 2011 15:21:44 -0000 Received: (qmail 25771 invoked by uid 22791); 9 Aug 2011 15:21:41 -0000 X-SWARE-Spam-Status: No, hits=-1.0 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,RCVD_IN_DNSWL_LOW,SPF_SOFTFAIL,TW_BJ,TW_CP,TW_DB,TW_YM X-Spam-Check-By: sourceware.org Received: from mail-gw0-f41.google.com (HELO mail-gw0-f41.google.com) (74.125.83.41) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 09 Aug 2011 15:21:22 +0000 Received: by gwaa20 with SMTP id a20so84157gwa.0 for ; Tue, 09 Aug 2011 08:21:22 -0700 (PDT) Received: by 10.142.126.1 with SMTP id y1mr6854780wfc.202.1312903281517; Tue, 09 Aug 2011 08:21:21 -0700 (PDT) Received: from localhost.localdomain ([203.110.240.178]) by mx.google.com with ESMTPS id s9sm46202pbk.66.2011.08.09.08.21.16 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 09 Aug 2011 08:21:20 -0700 (PDT) From: Sanjoy Das To: gdb-patches@sourceware.org Cc: Sanjoy Das Subject: [PATCH 4/7] Use the loaded reader. Date: Tue, 09 Aug 2011 15:21:00 -0000 Message-Id: <1312903509-25132-5-git-send-email-sanjoy@playingwithpointers.com> In-Reply-To: <1312903509-25132-1-git-send-email-sanjoy@playingwithpointers.com> References: <1312903509-25132-1-git-send-email-sanjoy@playingwithpointers.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-08/txt/msg00192.txt.bz2 Invoke the loaded JIT debug info reader to parse the registered symbol files. --- gdb/ChangeLog | 12 ++ gdb/jit.c | 428 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 410 insertions(+), 30 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 884b51a..bd63356 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,17 @@ 2011-08-09 Sanjoy Das + * jit.c (add_objfile_entry, jit_target_read_impl) + (jit_object_open_impl, jit_symtab_open_impl, compare_block) + (jit_block_open_impl, jit_block_open_impl) + (jit_symtab_line_mapping_impl, jit_symtab_close_impl) + (finalize_symtab, jit_object_close_impl) + (jit_reader_try_read_symtab, jit_bfd_try_read_symtab): New + functions. + (jit_register_code): Try using the loaded jit reader before + resorting to BFD. + +2011-08-09 Sanjoy Das + * jit.c (_initialize_jit): Add commands load-jit-reader and unload-jit-reader. (jit_reader_load): New function. diff --git a/gdb/jit.c b/gdb/jit.c index 3f83065..e81a386 100644 --- a/gdb/jit.c +++ b/gdb/jit.c @@ -21,8 +21,11 @@ #include "jit.h" #include "jit-reader.h" +#include "block.h" #include "breakpoint.h" #include "command.h" +#include "dictionary.h" +#include "frame-unwind.h" #include "gdbcmd.h" #include "gdbcore.h" #include "inferior.h" @@ -236,9 +239,19 @@ struct jit_inferior_data { CORE_ADDR breakpoint_addr; /* &__jit_debug_register_code() */ CORE_ADDR descriptor_addr; /* &__jit_debug_descriptor */ - struct objfile *jit_objfile; /* All the JIT symbols will be added to this. */ }; +/* Remember a mapping from entry_addr to objfile. */ +static void +add_objfile_entry (struct objfile *objfile, CORE_ADDR entry) +{ + CORE_ADDR *entry_addr_ptr; + + entry_addr_ptr = xmalloc (sizeof (CORE_ADDR)); + *entry_addr_ptr = entry; + set_objfile_data (objfile, jit_objfile_data, entry_addr_ptr); +} + /* Return jit_inferior_data for current inferior. Allocate if not already present. */ @@ -335,37 +348,369 @@ jit_read_code_entry (struct gdbarch *gdbarch, extract_unsigned_integer (&entry_buf[3 * ptr_size], 8, byte_order); } -/* This function registers code associated with a JIT code entry. It uses the - pointer and size pair in the entry to read the symbol file from the remote - and then calls symbol_file_add_from_local_memory to add it as though it were - a symbol file added by the user. */ +/* Proxy object for building a block. */ +struct gdb_block +{ + /* gdb_blocks are linked into a tree structure. Next points to the + next node at the same depth as this block and parent to the + parent gdb_block. */ + struct gdb_block *next, *parent; + struct block *real_block; + + /* The first and last code address corresponding to this block */ + CORE_ADDR begin, end; + /* The name of this block (if any). If this is non-NULL, the + FUNCTION symbol symbol is set to this value. */ + const char *name; +}; + +/* Proxy object for building a symtab. */ +struct gdb_symtab +{ + /* The list of blocks in this symtab. These will eventually be + converted to real blocks. */ + struct gdb_block *blocks; + /* The number of blocks inserted. */ + int nblocks; + /* A mapping between line numbers to PC. */ + struct linetable *linetable; + /* The source file for this symtab. */ + const char *file_name; + struct gdb_symtab *next; +}; + +/* Proxy object for building an object. */ +struct gdb_object +{ + struct gdb_symtab *symtabs; +}; + +/* The type of the `private' data passed around by the callback + functions. */ +struct jit_dbg_reader_data +{ + CORE_ADDR entry_address; +}; + +/* The reader calls into this function to read data off the targets + address space. */ +static enum gdb_status +jit_target_read_impl (GDB_CORE_ADDR target_mem, void *gdb_buf, int len) +{ + int result = target_read_memory ((CORE_ADDR) target_mem, gdb_buf, len); + if (result == 0) + return GDB_SUCCESS; + else + return GDB_FAIL; +} + +static struct gdb_object * +jit_object_open_impl (struct gdb_symbol_callbacks *cb) +{ + return XZALLOC (struct gdb_object); +} + +static struct gdb_symtab * +jit_symtab_open_impl (struct gdb_symbol_callbacks *cb, + struct gdb_object *object, + const char *file_name) +{ + struct gdb_symtab *ret = XZALLOC (struct gdb_symtab); + ret->file_name = file_name ? xstrdup (file_name) : xstrdup (""); + ret->next = object->symtabs; + object->symtabs = ret; + return ret; +} + +/* Returns true if the block corrensponding to old should be placed + before the block corresponding to new in the final blockvector. */ +static int +compare_block (struct gdb_block *old, struct gdb_block *new) +{ + if (old == NULL) + return 1; + if (old->begin < new->begin) + return 1; + else if (old->begin == new->begin) + { + if (old->end > new->end) + return 1; + else + return 0; + } + else + return 0; +} + +static struct gdb_block * +jit_block_open_impl (struct gdb_symbol_callbacks *cb, struct gdb_symtab *symtab, + struct gdb_block *parent, GDB_CORE_ADDR begin, + GDB_CORE_ADDR end, const char *name) +{ + struct gdb_block *block = XZALLOC (struct gdb_block); + + block->next = symtab->blocks; + block->begin = (CORE_ADDR) begin; + block->end = (CORE_ADDR) end; + block->name = name ? xstrdup (name) : NULL; + block->parent = parent; + + /* Ensure that the blocks are inserted in the correct (reverse of + the order expected by blockvector). */ + if (compare_block (symtab->blocks, block)) + { + symtab->blocks = block; + } + else + { + struct gdb_block *i = symtab->blocks; + + for (;; i = i->next) + { + /* Guaranteed to terminate, since compare_block (NULL, _) + returns 1 */ + if (compare_block (i->next, block)) + { + block->next = i->next; + i->next = block; + break; + } + } + } + symtab->nblocks++; + + return block; +} static void -jit_register_code (struct gdbarch *gdbarch, - CORE_ADDR entry_addr, struct jit_code_entry *code_entry) +jit_symtab_line_mapping_add_impl (struct gdb_symbol_callbacks *cb, + struct gdb_symtab *stab, int nlines, + struct gdb_line_mapping *map) +{ + int i; + if (!nlines) + return; + + stab->linetable = xmalloc (sizeof (struct linetable) + (nlines - 1) * + sizeof (struct linetable_entry)); + stab->linetable->nitems = nlines; + for (i = 0; i < nlines; i++) + { + stab->linetable->item [i].pc = (CORE_ADDR) map[i].pc; + stab->linetable->item [i].line = map[i].line; + } +} + +static void +jit_symtab_close_impl (struct gdb_symbol_callbacks *cb, struct gdb_symtab *stab) +{ +} + +/* Transform STAB to a proper symtab, and add it it OBJFILE. */ +static void +finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) { + struct symtab *symtab; + struct gdb_block *gdb_block_iter, *gdb_block_iter_tmp; + struct block *block_iter; + int actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks, i, blockvector_size; + CORE_ADDR begin, end; + + symtab = allocate_symtab (stab->file_name, objfile); + symtab->dirname = NULL; /* JIT compilers compile in memory */ + + /* Copy over the linetable entry if one was provided. */ + if (stab->linetable) + { + int size = (stab->linetable->nitems - 1) * + sizeof (struct linetable_entry) + sizeof (struct linetable); + LINETABLE (symtab) = obstack_alloc (&objfile->objfile_obstack, size); + memcpy (LINETABLE (symtab), stab->linetable, size); + } + else + { + LINETABLE (symtab) = NULL; + } + + blockvector_size = (sizeof (struct blockvector) + + (actual_nblocks - 1) * sizeof (struct block *)); + symtab->blockvector = obstack_alloc (&objfile->objfile_obstack, + blockvector_size); + + /* (begin, end) will contain the PC range this entire blockvector spans. */ + symtab->primary = 1; + BLOCKVECTOR_MAP (symtab->blockvector) = NULL; + begin = stab->blocks->begin; + end = stab->blocks->end; + BLOCKVECTOR_NBLOCKS (symtab->blockvector) = actual_nblocks; + + /* First run over all the gdb_block objects, creating a real block + object for each. Simultaneously, keep setting the real_block + fields. */ + for (i = (actual_nblocks - 1), gdb_block_iter = stab->blocks; + i >= FIRST_LOCAL_BLOCK; i--, gdb_block_iter = gdb_block_iter->next) + { + struct block *new_block = allocate_block (&objfile->objfile_obstack); + struct symbol *block_name = obstack_alloc (&objfile->objfile_obstack, + sizeof (struct symbol)); + + BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack, + NULL); + /* The address range. */ + BLOCK_START (new_block) = (CORE_ADDR) gdb_block_iter->begin; + BLOCK_END (new_block) = (CORE_ADDR) gdb_block_iter->end; + + /* The name. */ + memset (block_name, 0, sizeof (struct symbol)); + SYMBOL_DOMAIN (block_name) = VAR_DOMAIN; + SYMBOL_CLASS (block_name) = LOC_BLOCK; + block_name->symtab = symtab; + SYMBOL_BLOCK_VALUE (block_name) = new_block; + block_name->ginfo.name = obstack_alloc (&objfile->objfile_obstack, 1 + + strlen (gdb_block_iter->name)); + strcpy (block_name->ginfo.name, gdb_block_iter->name); + BLOCK_FUNCTION (new_block) = block_name; + + BLOCKVECTOR_BLOCK (symtab->blockvector, i) = new_block; + if (begin > BLOCK_START (new_block)) + begin = BLOCK_START (new_block); + if (end < BLOCK_END (new_block)) + end = BLOCK_END (new_block); + + gdb_block_iter->real_block = new_block; + } + + /* Now add the special blocks. */ + block_iter = NULL; + for (i = 0; i < FIRST_LOCAL_BLOCK; i++) + { + struct block *new_block = allocate_block (&objfile->objfile_obstack); + BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack, + NULL); + BLOCK_SUPERBLOCK (new_block) = block_iter; + block_iter = new_block; + + BLOCK_START (new_block) = (CORE_ADDR) begin; + BLOCK_END (new_block) = (CORE_ADDR) end; + + BLOCKVECTOR_BLOCK (symtab->blockvector, i) = new_block; + } + + /* Fill up the superblock fields for the real blocks, using the + real_block fields populated earlier. */ + for (gdb_block_iter = stab->blocks; gdb_block_iter; + gdb_block_iter = gdb_block_iter->next) + { + if (gdb_block_iter->parent != NULL) + BLOCK_SUPERBLOCK (gdb_block_iter->real_block) = + gdb_block_iter->parent->real_block; + } + + /* Free memory. */ + gdb_block_iter = stab->blocks; + for (gdb_block_iter = stab->blocks, gdb_block_iter_tmp = gdb_block_iter->next; + gdb_block_iter; gdb_block_iter = gdb_block_iter_tmp) + { + xfree ((void *) gdb_block_iter->name); + xfree (gdb_block_iter); + } + xfree (stab->linetable); + xfree ((char *) stab->file_name); + xfree (stab); +} + +/* Convert OBJ to a proper objfile. */ +static void +jit_object_close_impl (struct gdb_symbol_callbacks *cb, struct gdb_object *obj) +{ + struct gdb_symtab *i, *j = NULL; + struct objfile *objfile = allocate_objfile (NULL, 0); + struct jit_dbg_reader_data *priv_data = cb->priv_data; + + objfile->gdbarch = target_gdbarch; + objfile->msymbols = obstack_alloc (&objfile->objfile_obstack, + sizeof (struct minimal_symbol)); + objfile->msymbols[0].ginfo.name = NULL; + objfile->msymbols[0].ginfo.value.address = 0; + objfile->name = xstrdup ("JIT"); + + for (i = obj->symtabs; i; i = j) + { + j = i->next; + finalize_symtab (i, objfile); + } + add_objfile_entry (objfile, priv_data->entry_address); + xfree (obj); +} + +/* Try to read CODE_ENTRY using the loaded jit reader (if any). */ +static int +jit_reader_try_read_symtab (struct jit_code_entry *code_entry) +{ + void *gdb_mem; + int status = 0; + struct jit_dbg_reader *i; + struct jit_dbg_reader_data priv_data; + struct gdb_reader_funcs *funcs; + struct gdb_symbol_callbacks callbacks = + { + jit_object_open_impl, + jit_symtab_open_impl, + jit_block_open_impl, + jit_symtab_close_impl, + jit_object_close_impl, + + jit_symtab_line_mapping_add_impl, + jit_target_read_impl, + + &priv_data + }; + + priv_data.entry_address = code_entry->symfile_addr; + + if (!loaded_jit_reader) + return 0; + + gdb_mem = xmalloc (code_entry->symfile_size); + if (target_read_memory (code_entry->symfile_addr, gdb_mem, + code_entry->symfile_size)) + { + status = 0; + goto cleanup; + } + + funcs = loaded_jit_reader->functions; + if (funcs->read (funcs, &callbacks, gdb_mem, code_entry->symfile_size) + == GDB_SUCCESS) + { + status = 1; + goto cleanup; + } + + cleanup: + xfree (gdb_mem); + return status; +} + +/* Try to read CODE_ENTRY using BFD. */ +static void +jit_bfd_try_read_symtab (struct jit_code_entry *code_entry, + struct gdbarch *gdbarch) +{ + struct cleanup *old_cleanups; + struct objfile *objfile; bfd *nbfd; struct section_addr_info *sai; struct bfd_section *sec; - struct objfile *objfile; - struct cleanup *old_cleanups, *my_cleanups; - int i; const struct bfd_arch_info *b; - CORE_ADDR *entry_addr_ptr; - - if (jit_debug) - fprintf_unfiltered (gdb_stdlog, - "jit_register_code, symfile_addr = %s, " - "symfile_size = %s\n", - paddress (gdbarch, code_entry->symfile_addr), - pulongest (code_entry->symfile_size)); + int i; nbfd = bfd_open_from_target_memory (code_entry->symfile_addr, code_entry->symfile_size, gnutarget); old_cleanups = make_cleanup_bfd_close (nbfd); - /* Check the format. NOTE: This initializes important data that GDB uses! - We would segfault later without this line. */ + /* Check the format. NOTE: This initializes important data that GDB + uses! We would segfault later without this line. */ if (!bfd_check_format (nbfd, bfd_object)) { printf_unfiltered (_("\ @@ -381,17 +726,17 @@ JITed symbol file is not an object file, ignoring it.\n")); "with target architecture %s."), bfd_get_arch_info (nbfd)->printable_name, b->printable_name); - /* Read the section address information out of the symbol file. Since the - file is generated by the JIT at runtime, it should all of the absolute - addresses that we care about. */ + /* Read the section address information out of the symbol file. + Since the file is generated by the JIT at runtime, it should all + of the absolute addresses that we care about. */ sai = alloc_section_addr_info (bfd_count_sections (nbfd)); make_cleanup_free_section_addr_info (sai); i = 0; for (sec = nbfd->sections; sec != NULL; sec = sec->next) if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0) { - /* We assume that these virtual addresses are absolute, and do not - treat them as offsets. */ + /* We assume that these virtual addresses are absolute, and do + not treat them as offsets. */ sai->other[i].addr = bfd_get_section_vma (nbfd, sec); sai->other[i].name = xstrdup (bfd_get_section_name (nbfd, sec)); sai->other[i].sectindex = sec->index; @@ -401,12 +746,34 @@ JITed symbol file is not an object file, ignoring it.\n")); /* This call takes ownership of sai. */ objfile = symbol_file_add_from_bfd (nbfd, 0, sai, OBJF_SHARED, NULL); - /* Remember a mapping from entry_addr to objfile. */ - entry_addr_ptr = xmalloc (sizeof (CORE_ADDR)); - *entry_addr_ptr = entry_addr; - set_objfile_data (objfile, jit_objfile_data, entry_addr_ptr); - discard_cleanups (old_cleanups); + add_objfile_entry (objfile, code_entry->symfile_addr); +} + +/* This function registers code associated with a JIT code entry. It uses the + pointer and size pair in the entry to read the symbol file from the remote + and then calls symbol_file_add_from_local_memory to add it as though it were + a symbol file added by the user. */ + +static void +jit_register_code (struct gdbarch *gdbarch, + CORE_ADDR entry_addr, struct jit_code_entry *code_entry) +{ + int i, success; + const struct bfd_arch_info *b; + struct jit_inferior_data *inf_data = get_jit_inferior_data (); + + if (jit_debug) + fprintf_unfiltered (gdb_stdlog, + "jit_register_code, symfile_addr = %s, " + "symfile_size = %s\n", + paddress (gdbarch, code_entry->symfile_addr), + pulongest (code_entry->symfile_size)); + + success = jit_reader_try_read_symtab (code_entry); + + if (!success) + jit_bfd_try_read_symtab (code_entry, gdbarch); } /* This function unregisters JITed code and frees the corresponding @@ -415,6 +782,7 @@ JITed symbol file is not an object file, ignoring it.\n")); static void jit_unregister_code (struct objfile *objfile) { + xfree (objfile_data (objfile, jit_objfile_data)); free_objfile (objfile); } -- 1.7.5.4