From f997c383549db91a3f3b994a89201ad6498942b5 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Sun, 20 Nov 2011 08:30:59 +0000 Subject: [PATCH] gdb/ * Makefile.in: Add jit-reader.h as a header. Have it installed in $(includedir)/gdb. * configure.ac: Generate a correct value for TARGET_PTR for jit-reader.h. Tell configure to generate jit-reader.h from jit-reader.in. * configure: Re-generated by autoconf. * jit-reader.in: New file. * jit.c: Include jit-reader.h. --- gdb/ChangeLog | 11 ++ gdb/Makefile.in | 13 +- gdb/configure | 124 +++++++++++++++++ gdb/configure.ac | 22 +++ gdb/jit-reader.in | 344 ++++++++++++++++++++++++++++++++++++++++++++++ gdb/jit.c | 1 + 6 files changed, 511 insertions(+), 4 deletions(-) create mode 100644 gdb/jit-reader.in diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3e93b00e1dd..f09f3ca2208 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2011-11-20 Sanjoy Das + + * Makefile.in: Add jit-reader.h as a header. Have it installed in + $(includedir)/gdb. + * configure.ac: Generate a correct value for TARGET_PTR for + jit-reader.h. Tell configure to generate jit-reader.h from + jit-reader.in. + * configure: Re-generated by autoconf. + * jit-reader.in: New file. + * jit.c: Include jit-reader.h. + 2011-11-20 Sanjoy Das * MAINTAINERS (Write After Approval): Add myself to the list. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 7a7ff9f51aa..ff5f2460a42 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -833,7 +833,7 @@ common/linux-osdata.h # Header files that already have srcdir in them, or which are in objdir. -HFILES_WITH_SRCDIR = ../bfd/bfd.h +HFILES_WITH_SRCDIR = ../bfd/bfd.h jit-reader.h # GDB "info" files, which should be included in their entirety @@ -950,7 +950,7 @@ DISTSTUFF = $(YYFILES) # All generated files which can be included by another file. -generated_files = config.h observer.h observer.inc ada-lex.c \ +generated_files = config.h observer.h observer.inc ada-lex.c jit-reader.h \ $(GNULIB_H) $(NAT_GENERATED_FILES) .c.o: @@ -1035,7 +1035,9 @@ install-only: $(CONFIG_INSTALL) $(SHELL) $(srcdir)/../mkinstalldirs \ $(DESTDIR)$(man1dir) ; \ $(INSTALL_DATA) $(srcdir)/gdb.1 \ - $(DESTDIR)$(man1dir)/$$transformed_name.1 + $(DESTDIR)$(man1dir)/$$transformed_name.1 ; \ + $(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(includedir)/gdb ; \ + $(INSTALL_DATA) jit-reader.h $(DESTDIR)$(includedir)/gdb/jit-reader.h @$(MAKE) DO=install "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do .PHONY: install-tui install-tui: @@ -1263,7 +1265,7 @@ distclean: clean rm -f gdbserver/config.status gdbserver/config.log rm -f gdbserver/tm.h gdbserver/xm.h gdbserver/nm.h rm -f gdbserver/Makefile gdbserver/config.cache - rm -f nm.h config.status config.h stamp-h .gdbinit + rm -f nm.h config.status config.h stamp-h .gdbinit jit-reader.h rm -f y.output yacc.acts yacc.tmp y.tab.h rm -f config.log config.cache rm -f Makefile @@ -1329,6 +1331,9 @@ data-directory/Makefile: data-directory/Makefile.in config.status @frags@ CONFIG_LINKS= \ $(SHELL) config.status +jit-reader.h: $(srcdir)/jit-reader.in + $(SHELL) config.status $@ + config.h: stamp-h ; @true stamp-h: $(srcdir)/config.in config.status CONFIG_HEADERS=config.h:config.in \ diff --git a/gdb/configure b/gdb/configure index aec9d43d326..a206ee050a7 100755 --- a/gdb/configure +++ b/gdb/configure @@ -666,6 +666,7 @@ python_prog_path LTLIBEXPAT LIBEXPAT HAVE_LIBEXPAT +TARGET_PTR READLINE_TEXI_INCFLAG READLINE_CFLAGS READLINE_DEPS @@ -9884,6 +9885,128 @@ fi +# Generate jit-reader.h + +# This is typedeffed to GDB_CORE_ADDR in jit-reader.h +TARGET_PTR= + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long long" >&5 +$as_echo_n "checking size of unsigned long long... " >&6; } +if test "${ac_cv_sizeof_unsigned_long_long+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long long))" "ac_cv_sizeof_unsigned_long_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_unsigned_long_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "cannot compute sizeof (unsigned long long) +See \`config.log' for more details." "$LINENO" 5; }; } + else + ac_cv_sizeof_unsigned_long_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long_long" >&5 +$as_echo "$ac_cv_sizeof_unsigned_long_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_LONG_LONG $ac_cv_sizeof_unsigned_long_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5 +$as_echo_n "checking size of unsigned long... " >&6; } +if test "${ac_cv_sizeof_unsigned_long+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_unsigned_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "cannot compute sizeof (unsigned long) +See \`config.log' for more details." "$LINENO" 5; }; } + else + ac_cv_sizeof_unsigned_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long" >&5 +$as_echo "$ac_cv_sizeof_unsigned_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned __int128" >&5 +$as_echo_n "checking size of unsigned __int128... " >&6; } +if test "${ac_cv_sizeof_unsigned___int128+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned __int128))" "ac_cv_sizeof_unsigned___int128" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_unsigned___int128" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "cannot compute sizeof (unsigned __int128) +See \`config.log' for more details." "$LINENO" 5; }; } + else + ac_cv_sizeof_unsigned___int128=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned___int128" >&5 +$as_echo "$ac_cv_sizeof_unsigned___int128" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED___INT128 $ac_cv_sizeof_unsigned___int128 +_ACEOF + + + +if test "x${ac_cv_sizeof_unsigned_long}" = "x8"; then + TARGET_PTR="unsigned long" +elif test "x${ac_cv_sizeof_unsigned_long_long}" = "x8"; then + TARGET_PTR="unsigned long long" +elif test "x${ac_cv_sizeof_unsigned___int128}" = "x16"; then + TARGET_PTR="unsigned __int128" +else + TARGET_PTR="unsigned long" +fi + + +ac_config_files="$ac_config_files jit-reader.h:jit-reader.in" + + # Check whether --with-expat was given. if test "${with_expat+set}" = set; then : @@ -16794,6 +16917,7 @@ do "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.in" ;; "depdir") CONFIG_COMMANDS="$CONFIG_COMMANDS depdir" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "jit-reader.h") CONFIG_FILES="$CONFIG_FILES jit-reader.h:jit-reader.in" ;; "$ac_config_links_1") CONFIG_LINKS="$CONFIG_LINKS $ac_config_links_1" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; ".gdbinit") CONFIG_FILES="$CONFIG_FILES .gdbinit:gdbinit.in" ;; diff --git a/gdb/configure.ac b/gdb/configure.ac index fbbb2de55de..ac8707af54b 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -605,6 +605,28 @@ AC_SUBST(READLINE_DEPS) AC_SUBST(READLINE_CFLAGS) AC_SUBST(READLINE_TEXI_INCFLAG) +# Generate jit-reader.h + +# This is typedeffed to GDB_CORE_ADDR in jit-reader.h +TARGET_PTR= + +AC_CHECK_SIZEOF(unsigned long long) +AC_CHECK_SIZEOF(unsigned long) +AC_CHECK_SIZEOF(unsigned __int128) + +if test "x${ac_cv_sizeof_unsigned_long}" = "x8"; then + TARGET_PTR="unsigned long" +elif test "x${ac_cv_sizeof_unsigned_long_long}" = "x8"; then + TARGET_PTR="unsigned long long" +elif test "x${ac_cv_sizeof_unsigned___int128}" = "x16"; then + TARGET_PTR="unsigned __int128" +else + TARGET_PTR="unsigned long" +fi + +AC_SUBST(TARGET_PTR) +AC_CONFIG_FILES([jit-reader.h:jit-reader.in]) + AC_ARG_WITH(expat, AS_HELP_STRING([--with-expat], [include expat support (auto/yes/no)]), [], [with_expat=auto]) diff --git a/gdb/jit-reader.in b/gdb/jit-reader.in new file mode 100644 index 00000000000..3efe722fc6d --- /dev/null +++ b/gdb/jit-reader.in @@ -0,0 +1,344 @@ +/* JIT declarations for GDB, the GNU Debugger. + + Copyright (C) 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef GDB_JIT_READER_H +#define GDB_JIT_READER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Versioning information. See gdb_reader_funcs. */ + +#define GDB_READER_INTERFACE_VERSION 1 + +/* Readers must be released under a GPL compatible license. To + declare that the reader is indeed released under a GPL compatible + license, invoke the macro GDB_DECLARE_GPL_COMPATIBLE in a source + file. */ + +#ifdef __cplusplus +#define GDB_DECLARE_GPL_COMPATIBLE_READER \ + extern "C" { \ + extern int plugin_is_GPL_compatible (void) \ + { \ + return 0; \ + } \ + } + +#else + +#define GDB_DECLARE_GPL_COMPATIBLE_READER + extern int plugin_is_GPL_compatible (void) \ + { \ + return 0; \ + } + +#endif + +/* Represents an address on the target system. */ + +typedef @TARGET_PTR@ GDB_CORE_ADDR; + +/* Return status codes. */ + +enum gdb_status { + GDB_FAIL = 0, + GDB_SUCCESS = 1 +}; + +struct gdb_object; +struct gdb_symtab; +struct gdb_block; +struct gdb_symbol_callbacks; + +/* An array of these are used to represent a map from code addresses to line + numbers in the source file. */ + +struct gdb_line_mapping +{ + int line; + GDB_CORE_ADDR pc; +}; + +/* Create a new GDB code object. Each code object can have one or + more symbol tables, each representing a compiled source file. */ + +typedef struct gdb_object *(gdb_object_open) (struct gdb_symbol_callbacks *cb); + +/* The callback used to create new symbol table. CB is the + gdb_symbol_callbacks which the structure is part of. FILE_NAME is + an (optionally NULL) file name to associate with this new symbol + table. + + Returns a new instance to gdb_symtab that can later be passed to + gdb_block_new, gdb_symtab_add_line_mapping and gdb_symtab_close. */ + +typedef struct gdb_symtab *(gdb_symtab_open) (struct gdb_symbol_callbacks *cb, + struct gdb_object *obj, + const char *file_name); + +/* Creates a new block in a given symbol table. A symbol table is a + forest of blocks, each block representing an code address range and + a corresponding (optionally NULL) NAME. In case the block + corresponds to a function, the NAME passed should be the name of + the function. + + If the new block to be created is a child of (i.e. is nested in) + another block, the parent block can be passed in PARENT. SYMTAB is + the symbol table the new block is to belong in. BEGIN, END is the + code address range the block corresponds to. + + Returns a new instance of gdb_block, which, as of now, has no use. + Note that the gdb_block returned must not be freed by the + caller. */ + +typedef struct gdb_block *(gdb_block_open) (struct gdb_symbol_callbacks *cb, + struct gdb_symtab *symtab, + struct gdb_block *parent, + GDB_CORE_ADDR begin, + GDB_CORE_ADDR end, + const char *name); + +/* Adds a PC to line number mapping for the symbol table SYMTAB. + NLINES is the number of elements in LINES, each element + corresponding to one (PC, line) pair. */ + +typedef void (gdb_symtab_add_line_mapping) (struct gdb_symbol_callbacks *cb, + struct gdb_symtab *symtab, + int nlines, + struct gdb_line_mapping *lines); + +/* Close the symtab SYMTAB. This signals to GDB that no more blocks + will be opened on this symtab. */ + +typedef void (gdb_symtab_close) (struct gdb_symbol_callbacks *cb, + struct gdb_symtab *symtab); + + +/* Closes the gdb_object OBJ and adds the emitted information into + GDB's internal structures. Once this is done, the debug + information will be picked up and used; this will usually be the + last operation in gdb_read_debug_info. */ + +typedef void (gdb_object_close) (struct gdb_symbol_callbacks *cb, + struct gdb_object *obj); + +/* Reads LEN bytes from TARGET_MEM in the target's virtual address + space into GDB_BUF. + + Returns GDB_FAIL on failure, and GDB_SUCCESS on success. */ + +typedef enum gdb_status (gdb_target_read) (GDB_CORE_ADDR target_mem, + void *gdb_buf, int len); + +/* The list of callbacks that are passed to read. These callbacks are + to be used to construct the symbol table. The functions have been + described above. */ + +struct gdb_symbol_callbacks +{ + gdb_object_open *object_open; + gdb_symtab_open *symtab_open; + gdb_block_open *block_open; + gdb_symtab_close *symtab_close; + gdb_object_close *object_close; + + gdb_symtab_add_line_mapping *line_mapping_add; + gdb_target_read *target_read; + + /* For internal use by GDB. */ + void *priv_data; +}; + +/* Forward declaration. */ + +struct gdb_reg_value; + +/* A function of this type is used to free a gdb_reg_value. See the + comment on `free' in struct gdb_reg_value. */ + +typedef void (gdb_reg_value_free) (struct gdb_reg_value *); + +/* Denotes the value of a register. */ + +struct gdb_reg_value +{ + /* The size of the register in bytes. The reader need not set this + field. This will be set for (defined) register values being read + from GDB using reg_get. */ + int size; + + /* Set to non-zero if the value for the register is known. The + registers for which the reader does not call reg_set are also + assumed to be undefined */ + int defined; + + /* Since gdb_reg_value is a variable sized structure, it will + usually be allocated on the heap. This function is expected to + contain the corresponding "free" function. + + When a pointer to gdb_reg_value is being sent from GDB to the + reader (via gdb_unwind_reg_get), the reader is expected to call + this function (with the same gdb_reg_value as argument) once it + is done with the value. + + When the function sends the a gdb_reg_value to GDB (via + gdb_unwind_reg_set), it is expected to set this field to point to + an appropriate cleanup routine (or to NULL if no cleanup is + required). */ + gdb_reg_value_free *free; + + /* The value of the register. */ + unsigned char value[1]; +}; + +/* get_frame_id in gdb_reader_funcs is to return a gdb_frame_id + corresponding to the current frame. The registers corresponding to + the current frame can be read using reg_get. Calling get_frame_id + on a particular frame should return the same gdb_frame_id + throughout its lifetime (i.e. till before it gets unwound). One + way to do this is by having the CODE_ADDRESS point to the + function's first instruction and STACK_ADDRESS point to the value + of the stack pointer when entering the function. */ + +struct gdb_frame_id +{ + GDB_CORE_ADDR code_address; + GDB_CORE_ADDR stack_address; +}; + +/* Forward declaration. */ + +struct gdb_unwind_callbacks; + +/* Returns the value of a particular register in the current frame. + The current frame is the frame that needs to be unwound into the + outer (earlier) frame. + + CB is the struct gdb_unwind_callbacks * the callback belongs to. + REGNUM is the DWARF register number of the register that needs to + be unwound. + + Returns the gdb_reg_value corresponding to the register requested. + In case the value of the register has been optimized away or + otherwise unavailable, the defined flag in the returned + gdb_reg_value will be zero. */ + +typedef struct gdb_reg_value *(gdb_unwind_reg_get) + (struct gdb_unwind_callbacks *cb, int regnum); + +/* Sets the previous value of a particular register. REGNUM is the + (DWARF) register number whose value is to be set. VAL is the value + the register is to be set to. + + VAL is *not* copied, so the memory allocated to it cannot be + reused. Once GDB no longer needs the value, it is deallocated + using the FREE function (see gdb_reg_value). + + A register can also be "set" to an undefined value by setting the + defined in VAL to zero. */ + +typedef void (gdb_unwind_reg_set) (struct gdb_unwind_callbacks *cb, int regnum, + struct gdb_reg_value *val); + +/* This struct is passed to unwind in gdb_reader_funcs, and is to be + used to unwind the current frame (current being the frame whose + registers can be read using reg_get) into the earlier frame. The + functions have been described above. */ + +struct gdb_unwind_callbacks +{ + gdb_unwind_reg_get *reg_get; + gdb_unwind_reg_set *reg_set; + gdb_target_read *target_read; + + /* For internal use by GDB. */ + void *priv_data; +}; + +/* Forward declaration. */ + +struct gdb_reader_funcs; + +/* Parse the debug info off a block of memory, pointed to by MEMORY + (already copied to GDB's address space) and MEMORY_SZ bytes long. + The implementation has to use the functions in CB to actually emit + the parsed data into GDB. SELF is the same structure returned by + gdb_init_reader. + + Return GDB_FAIL on failure and GDB_SUCCESS on success. */ + +typedef enum gdb_status (gdb_read_debug_info) (struct gdb_reader_funcs *self, + struct gdb_symbol_callbacks *cb, + void *memory, long memory_sz); + +/* Unwind the current frame, CB is the set of unwind callbacks that + are to be used to do this. + + Return GDB_FAIL on failure and GDB_SUCCESS on success. */ + +typedef enum gdb_status (gdb_unwind_frame) (struct gdb_reader_funcs *self, + struct gdb_unwind_callbacks *cb); + +/* Return the frame ID corresponding to the current frame, using C to + read the current register values. See the comment on struct + gdb_frame_id. */ + +typedef struct gdb_frame_id (gdb_get_frame_id) (struct gdb_reader_funcs *self, + struct gdb_unwind_callbacks *c); + +/* Called when a reader is being unloaded. This function should also + free SELF, if required. */ + +typedef void (gdb_destroy_reader) (struct gdb_reader_funcs *self); + +/* Called when the reader is loaded. Must either return a properly + populated gdb_reader_funcs or NULL. The memory allocated for the + gdb_reader_funcs is to be managed by the reader itself (i.e. if it + is allocated from the heap, it must also be freed in + gdb_destroy_reader). */ + +extern struct gdb_reader_funcs *gdb_init_reader (void); + +/* Pointer to the functions which implement the reader's + functionality. The individual functions have been documented + above. + + None of the fields are optional. */ + +struct gdb_reader_funcs +{ + /* Must be set to GDB_READER_INTERFACE_VERSION. */ + int reader_version; + + /* For use by the reader. */ + void *priv_data; + + gdb_read_debug_info *read; + gdb_unwind_frame *unwind; + gdb_get_frame_id *get_frame_id; + gdb_destroy_reader *destroy; +}; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/gdb/jit.c b/gdb/jit.c index 954d297309a..85e40ac8be3 100644 --- a/gdb/jit.c +++ b/gdb/jit.c @@ -20,6 +20,7 @@ #include "defs.h" #include "jit.h" +#include "jit-reader.h" #include "breakpoint.h" #include "command.h" #include "gdbcmd.h" -- 2.30.2