diff --git a/contrib/gdb/configure.in b/contrib/gdb/configure.in index baf9d73ebab7..cca09647934d 100644 --- a/contrib/gdb/configure.in +++ b/contrib/gdb/configure.in @@ -54,7 +54,7 @@ libstdcxx_flags='`case $$dir in libstdc++-v3 | libjava) ;; *) test ! -f $$r/$(TA # these tools are built for the host environment # Note, the powerpc-eabi build depends on sim occurring before gdb in order to # know that we are building the simulator. -host_tools="texinfo byacc flex bison binutils ld gas gcc cgen sid sim gdb make patch prms send-pr gprof gdbtest tgas etc expect dejagnu ash bash bzip2 m4 autoconf automake libtool ispell grep diff rcs cvssrc fileutils shellutils time textutils wdiff find emacs emacs19 uudecode hello tar gzip indent recode release sed utils guile perl apache inet gawk findutils snavigator libtool gettext zip" +host_tools="byacc flex bison binutils ld gas gcc cgen sid sim gdb make patch prms send-pr gprof gdbtest tgas etc expect dejagnu ash bash bzip2 m4 autoconf automake libtool ispell grep diff rcs cvssrc fileutils shellutils time textutils wdiff find emacs emacs19 uudecode hello tar gzip indent recode release sed utils guile perl apache inet gawk findutils snavigator libtool gettext zip" # these libraries are built for the target environment, and are built after # the host libraries and the host tools (which may be a cross compiler) diff --git a/contrib/gdb/gdb/ChangeLog b/contrib/gdb/gdb/ChangeLog index 5bc9ff712a38..3a9cf50e05f2 100644 --- a/contrib/gdb/gdb/ChangeLog +++ b/contrib/gdb/gdb/ChangeLog @@ -1,3 +1,108 @@ +2002-07-19 GDB Administrator + + GDB 5.2.1 released. + * version.in: Bump to version 5.2.1 + * README, NEWS: Update to refer to GDB 5.2.1. + +2002-07-19 Andrew Cagney + + * Makefile.in (x86-64-tdep.o): Add $(objfiles_h). + * x86-64-tdep.c: Include "objfiles.h". + (x86_64_gdbarch_init): Set in_solib_call_trampoline to + in_plt_section. From 2002-07-18 Michal Ludvig . + +2002-07-15 Andrew Cagney + + From Gerhard Tonn : + * s390-nat.c (fill_fpregset, fill_gregset): Use regcache_collect + instead of supply_register. + +2002-07-15 Andrew Cagney + + * dwarf2cfi.c: Replace __func__ with "?func?". + +2002-07-09 David O'Brien + + Merge from mainline: + * gdbserver/gdbreplay.c: Include needed system headers. + (remote_open): Conditional strchr prototype. + (perror_with_name, remote_close, remote_open, expect, play): Static. + +2002-07-09 Michal Ludvig + + * NEWS: Note about dwarf2cfi improvements. + +2002-07-09 Pierre Muller + + Merge from mainline: + + 2002-07-04 Pierre Muller + * i386-nat.c (child_post_startup_inferior): New function + calling i386_cleanup_dregs if + I386_USE_GENERIC_WATCHPOINTS is defined. + * config/i386/nm-i386.h: define CHILD_POST_STARTUP_INFERIOR + conditional to acknowledge that i386-nat.c has its + own child_post_startup_inferior function. + +2002-07-03 Michal Ludvig + + Merge from mainline: + + 2002-06-21 Michal Ludvig + * dwarf2cfi.c (read_encoded_pointer): Don't handle pointer + encoding anymore. + (pointer_encoding, enum ptr_encoding): New. + (execute_cfa_program): Take care about pointer encoding. + (dwarf2_build_frame_info): Only call parse_frame_info for + .debug_frame and .eh_frame. + (parse_frame_info): New, derived from former dwarf2_build_frame_info. + fixed augmentation handling, added relative addressing, + ignore duplicate FDEs. Added comments. + * dwarf2cfi.c: Reindented. + + 2002-06-20 Michal Ludvig + * x86-64-tdep.c (x86_64_register_nr2name): Rename to + x86_64_register_name. Return type changed to 'const char *'. + (x86_64_register_name2nr): Rename to x86_64_register_number. + (x86_64_gdbarch_init): Update to reflect the change. + * x86-64-tdep.h: Ditto. + * x86-64-linux-nat.c (x86_64_fxsave_offset) + (supply_fpregset): Ditto. + + 2002-06-11 Michal Ludvig + * dwarf2cfi.c (unwind_tmp_obstack_init): New. + (unwind_tmp_obstack_free, parse_frame_info) + (update_context, cfi_read_fp, cfi_write_fp) + (cfi_frame_chain, cfi_init_extra_frame_info) + (cfi_virtual_frame_pointer): Use the above function. + * x86-64-tdep.c (x86_64_skip_prologue): Fix to work on functions + without debug information too. + + 2002-06-07 Michal Ludvig + * x86-64-linux-nat.c (x86_64_fxsave_offset): New. + (supply_fpregset, fill_fpregset): Don't call i387_*_fxsave, + better do the things actually here. + * x86-64-tdep.c (x86_64_register_name2nr): New. + (x86_64_register_name): Renamed to x86_64_register_nr2name. + (x86_64_gdbarch_init): Respect the above change. + * x86-64-tdep.h (x86_64_register_name2nr) + (x86_64_register_nr2name): Add prototypes. + * config/i386/x86-64linux.mt (TDEPFILES): Remove i387-tdep.o. + +2002-06-28 Andrew Cagney + + * Makefile.in (objfiles_h): Add $(bcache_h). + * objfiles.h: Include "bcache.h". + + * Makefile.in (symtab_h): Remove $(bcache_h). + * symtab.h: Do not include "bcache.h". + +2002-06-28 David O'Brien + + Merge from mainline: + * config/i386/nm-fbsd.h: Include . + * config/i386/tm-fbsd.h: Likewise. + 2002-06-22 Andrew Cagney * NEWS: Mention below. diff --git a/contrib/gdb/gdb/Makefile.in b/contrib/gdb/gdb/Makefile.in index 3b31aed8870d..a741ace3c206 100644 --- a/contrib/gdb/gdb/Makefile.in +++ b/contrib/gdb/gdb/Makefile.in @@ -624,7 +624,7 @@ language_h = language.h linespec_h = linespec.h memattr_h = memattr.h monitor_h = monitor.h -objfiles_h = objfiles.h +objfiles_h = objfiles.h $(bcache_h) parser_defs_h = parser-defs.h $(doublest_h) regcache_h = regcache.h remote_h = remote.h @@ -635,7 +635,7 @@ solist_h = solist.h source_h = source.h stabsread_h = stabsread.h symfile_h = symfile.h -symtab_h = symtab.h $(bcache_h) +symtab_h = symtab.h target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h) terminal_h = terminal.h top_h = top.h @@ -2135,9 +2135,9 @@ vax-tdep.o: vax-tdep.c $(OP_INCLUDE)/vax.h $(defs_h) $(symtab_h) x86-64-linux-tdep.o : x86-64-linux-tdep.c $(defs_h) $(inferior_h) \ $(gdbcore_h) $(regcache_h) x86-64-tdep.h i386-tdep.h $(dwarf2cfi_h) -x86-64-tdep.o : x86-64-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) $(gdbcmd_h) \ - $(arch_utils_h) $(regcache_h) $(symfile_h) x86-64-tdep.h i386-tdep.h \ - $(dwarf2cfi_h) gdb_assert.h +x86-64-tdep.o : x86-64-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) \ + $(gdbcmd_h) $(arch_utils_h) $(regcache_h) $(symfile_h) x86-64-tdep.h \ + i386-tdep.h $(dwarf2cfi_h) gdb_assert.h $(objfiles_h) x86-64-linux-nat.o : x86-64-linux-nat.c $(defs_h) $(inferior_h) \ $(gdbcore_h) $(regcache_h) i387-nat.h gdb_assert.h x86-64-tdep.h \ diff --git a/contrib/gdb/gdb/NEWS b/contrib/gdb/gdb/NEWS index d7c0ad0c15d4..f3acc60ffc5e 100644 --- a/contrib/gdb/gdb/NEWS +++ b/contrib/gdb/gdb/NEWS @@ -1,7 +1,7 @@ What has changed in GDB? (Organized release by release) -*** Changes since GDB 5.2: +*** Changes in GDB 5.2.1: * New targets. @@ -17,6 +17,14 @@ gdb/439: gdb/291: On some ELF object files, gdb was reporting: dwarf2read.c:1072: gdb-internal-error: sect_index_text not initialize Fix, by Fred Fish, imported from mainline. +Dwarf2 .debug_frame & .eh_frame handler improved in many ways. +Surprisingly enough, it works now. +By Michal Ludvig, imported from mainline. + +i386 hardware watchpoint support: +avoid misses on second run for some targets. +By Pierre Muller, imported from mainline. + *** Changes in GDB 5.2: * New command "set trust-readonly-sections on[off]". diff --git a/contrib/gdb/gdb/README b/contrib/gdb/gdb/README index 8af440fbd68f..47c490c2f0d1 100644 --- a/contrib/gdb/gdb/README +++ b/contrib/gdb/gdb/README @@ -1,5 +1,5 @@ - README for gdb-5.2 release - Updated 17 April, 2002 by Andrew Cagney + README for gdb-5.2.1 release + Updated 19 July, 2002 by Andrew Cagney This is GDB, the GNU source-level debugger. @@ -20,7 +20,7 @@ Unpacking and Installation -- quick overview In this release, the GDB debugger sources, the generic GNU include files, the BFD ("binary file description") library, the readline library, and other libraries all have directories of their own -underneath the gdb-5.2 directory. The idea is that a variety of GNU +underneath the gdb-5.2.1 directory. The idea is that a variety of GNU tools can share a common copy of these things. Be aware of variation over time--for example don't try to build gdb with a copy of bfd from a release other than the gdb release (such as a binutils release), @@ -29,8 +29,8 @@ Configuration scripts and makefiles exist to cruise up and down this directory tree and automatically build all the pieces in the right order. - When you unpack the gdb-5.2.tar.gz file, you'll find a directory -called `gdb-5.2', which contains: + When you unpack the gdb-5.2.1.tar.gz file, you'll find a directory +called `gdb-5.2.1', which contains: COPYING config.sub intl missing opcodes COPYING.LIB configure libiberty mkinstalldirs readline @@ -44,7 +44,7 @@ called `gdb-5.2', which contains: You can build GDB right in the source directory: - cd gdb-5.2 + cd gdb-5.2.1 ./configure make cp gdb/gdb /usr/local/bin/gdb (or wherever you want) @@ -58,12 +58,12 @@ You can build GDB in any empty build directory: mkdir build cd build - /gdb-5.2/configure + /gdb-5.2.1/configure make cp gdb/gdb /usr/local/bin/gdb (or wherever you want) (Building GDB with DJGPP tools for MS-DOS/MS-Windows is slightly -different; see the file gdb-5.2/gdb/config/djgpp/README for details.) +different; see the file gdb-5.2.1/gdb/config/djgpp/README for details.) This will configure and build all the libraries as well as GDB. If `configure' can't determine your system type, specify one as its @@ -94,7 +94,7 @@ documentation and TeX (or `texi2roff') to typeset the printed version. GDB includes an already formatted copy of the on-line Info version of this manual in the `gdb/doc' subdirectory. The main Info file is -`gdb-5.2/gdb/doc/gdb.info', and it refers to subordinate files +`gdb-5.2.1/gdb/doc/gdb.info', and it refers to subordinate files matching `gdb.info*' in the same directory. If necessary, you can print out these files, or read them with any editor; but they are easier to read using the `info' subsystem in GNU Emacs or the @@ -106,7 +106,7 @@ Info formatting programs, such as `texinfo-format-buffer' or `makeinfo'. If you have `makeinfo' installed, and are in the top level GDB -source directory (`gdb-5.2', in the case of version 5.2), you can make +source directory (`gdb-5.2.1', in the case of version 5.2.1), you can make the Info file by typing: cd gdb/doc @@ -115,7 +115,7 @@ the Info file by typing: If you want to typeset and print copies of this manual, you need TeX, a program to print its DVI output files, and `texinfo.tex', the Texinfo definitions file. This file is included in the GDB -distribution, in the directory `gdb-5.2/texinfo'. +distribution, in the directory `gdb-5.2.1/texinfo'. TeX is a typesetting program; it does not print files directly, but produces output files called DVI files. To print a typeset document, @@ -129,11 +129,11 @@ without any extension or a `.dvi' extension. This file tells TeX how to typeset a document written in Texinfo format. On its own, TeX cannot read, much less typeset a Texinfo file. `texinfo.tex' is distributed with GDB and is located in the -`gdb-5.2/texinfo' directory. +`gdb-5.2.1/texinfo' directory. If you have TeX and a DVI printer program installed, you can typeset and print this manual. First switch to the the `gdb' subdirectory of -the main source directory (for example, to `gdb-5.2/gdb') and then type: +the main source directory (for example, to `gdb-5.2.1/gdb') and then type: make doc/gdb.dvi @@ -156,55 +156,55 @@ preparing GDB for installation; you can then use `make' to build the a single directory, whose name is usually composed by appending the version number to `gdb'. - For example, the GDB version 5.2 distribution is in the `gdb-5.2' + For example, the GDB version 5.2.1 distribution is in the `gdb-5.2.1' directory. That directory contains: -`gdb-5.2/{COPYING,COPYING.LIB}' +`gdb-5.2.1/{COPYING,COPYING.LIB}' Standard GNU license files. Please read them. -`gdb-5.2/bfd' +`gdb-5.2.1/bfd' source for the Binary File Descriptor library -`gdb-5.2/config*' +`gdb-5.2.1/config*' script for configuring GDB, along with other support files -`gdb-5.2/gdb' +`gdb-5.2.1/gdb' the source specific to GDB itself -`gdb-5.2/include' +`gdb-5.2.1/include' GNU include files -`gdb-5.2/libiberty' +`gdb-5.2.1/libiberty' source for the `-liberty' free software library -`gdb-5.2/mmalloc' +`gdb-5.2.1/mmalloc' source for the GNU memory-mapped malloc package -`gdb-5.2/opcodes' +`gdb-5.2.1/opcodes' source for the library of opcode tables and disassemblers -`gdb-5.2/readline' +`gdb-5.2.1/readline' source for the GNU command-line interface NOTE: The readline library is compiled for use by GDB, but will not be installed on your system when "make install" is issued. -`gdb-5.2/sim' +`gdb-5.2.1/sim' source for some simulators (ARM, D10V, SPARC, M32R, MIPS, PPC, V850, etc) -`gdb-5.2/intl' +`gdb-5.2.1/intl' source for the GNU gettext library, for internationalization. This is slightly modified from the standalone gettext distribution you can get from GNU. -`gdb-5.2/texinfo' +`gdb-5.2.1/texinfo' The `texinfo.tex' file, which you need in order to make a printed manual using TeX. -`gdb-5.2/etc' +`gdb-5.2.1/etc' Coding standards, useful files for editing GDB, and other miscellanea. -`gdb-5.2/utils' +`gdb-5.2.1/utils' A grab bag of random utilities. Note: the following instructions are for building GDB on Unix or @@ -213,14 +213,14 @@ MS-DOS/MS-Windows are in the file gdb/config/djgpp/README. The simplest way to configure and build GDB is to run `configure' from the `gdb-VERSION-NUMBER' source directory, which in this example -is the `gdb-5.2' directory. +is the `gdb-5.2.1' directory. First switch to the `gdb-VERSION-NUMBER' source directory if you are not already in it; then run `configure'. For example: - cd gdb-5.2 + cd gdb-5.2.1 ./configure make @@ -236,8 +236,8 @@ you may need to run `sh' on it explicitly: sh configure If you run `configure' from a directory that contains source -directories for multiple libraries or programs, such as the `gdb-5.2' -source directory for version 5.2, `configure' creates configuration +directories for multiple libraries or programs, such as the `gdb-5.2.1' +source directory for version 5.2.1, `configure' creates configuration files for every directory level underneath (unless you tell it not to, with the `--norecursion' option). @@ -245,10 +245,10 @@ with the `--norecursion' option). directories in the GDB distribution, if you only want to configure that subdirectory; but be sure to specify a path to it. - For example, with version 5.2, type the following to configure only + For example, with version 5.2.1, type the following to configure only the `bfd' subdirectory: - cd gdb-5.2/bfd + cd gdb-5.2.1/bfd ../configure You can install `gdb' anywhere; it has no hardwired paths. However, @@ -277,13 +277,13 @@ directory. If the path to `configure' would be the same as the argument to `--srcdir', you can leave out the `--srcdir' option; it will be assumed.) - For example, with version 5.2, you can build GDB in a separate + For example, with version 5.2.1, you can build GDB in a separate directory for a Sun 4 like this: - cd gdb-5.2 + cd gdb-5.2.1 mkdir ../gdb-sun4 cd ../gdb-sun4 - ../gdb-5.2/configure + ../gdb-5.2.1/configure make When `configure' builds a configuration using a remote source @@ -304,8 +304,8 @@ called `configure' (or one of its subdirectories). The `Makefile' that `configure' generates in each source directory also runs recursively. If you type `make' in a source directory such -as `gdb-5.2' (or in a separate configured directory configured with -`--srcdir=PATH/gdb-5.2'), you will build all the required libraries, +as `gdb-5.2.1' (or in a separate configured directory configured with +`--srcdir=PATH/gdb-5.2.1'), you will build all the required libraries, and then build GDB. When you have multiple hosts or targets configured in separate @@ -348,7 +348,7 @@ you can use it to test your guesses on abbreviations--for example: Invalid configuration `i786v': machine `i786v' not recognized `config.sub' is also distributed in the GDB source directory -(`gdb-5.2', for version 5.2). +(`gdb-5.2.1', for version 5.2.1). `configure' options @@ -496,7 +496,7 @@ As an alternative, the bug report can be submitted, via e-mail, to the address "bug-gdb@gnu.org". When submitting a bug, please include the GDB version number (e.g., -gdb-5.2), and how you configured it (e.g., "sun4" or "mach386 host, +gdb-5.2.1), and how you configured it (e.g., "sun4" or "mach386 host, i586-intel-synopsys target"). Since GDB now supports so many different configurations, it is important that you be precise about this. If at all possible, you should include the actual banner that @@ -551,17 +551,17 @@ ftp://sources.redhat.com/pub/dejagnu/ will contain a recent snapshot. Once DejaGNU is installed, you can run the tests in one of the following ways: - (1) cd gdb-5.2 + (1) cd gdb-5.2.1 make check-gdb or - (2) cd gdb-5.2/gdb + (2) cd gdb-5.2.1/gdb make check or - (3) cd gdb-5.2/gdb/testsuite + (3) cd gdb-5.2.1/gdb/testsuite make site.exp (builds the site specific file) runtest -tool gdb GDB=../gdb (or GDB= as appropriate) diff --git a/contrib/gdb/gdb/config/i386/nm-fbsd.h b/contrib/gdb/gdb/config/i386/nm-fbsd.h index 939b880817be..a06ce955d6c7 100644 --- a/contrib/gdb/gdb/config/i386/nm-fbsd.h +++ b/contrib/gdb/gdb/config/i386/nm-fbsd.h @@ -28,6 +28,10 @@ #include "i386/nm-i386.h" +#ifdef HAVE_SYS_PARAM_H +#include +#endif + /* Provide access to the i386 hardware debugging registers. */ #define I386_DR_LOW_SET_CONTROL(control) \ diff --git a/contrib/gdb/gdb/config/i386/nm-i386.h b/contrib/gdb/gdb/config/i386/nm-i386.h index 500bf7b59423..eed05a476fa3 100644 --- a/contrib/gdb/gdb/config/i386/nm-i386.h +++ b/contrib/gdb/gdb/config/i386/nm-i386.h @@ -115,6 +115,10 @@ extern int i386_remove_hw_breakpoint (CORE_ADDR addr, void *shadow); #define DECR_PC_AFTER_HW_BREAK 0 +/* child_post_startup_inferior used to + reset all debug registers by calling i386_cleanup_dregs (). */ +#define CHILD_POST_STARTUP_INFERIOR + #endif /* I386_USE_GENERIC_WATCHPOINTS */ #endif /* NM_I386_H */ diff --git a/contrib/gdb/gdb/config/i386/tm-fbsd.h b/contrib/gdb/gdb/config/i386/tm-fbsd.h index 61f5de57f4a7..5c819ce5250d 100644 --- a/contrib/gdb/gdb/config/i386/tm-fbsd.h +++ b/contrib/gdb/gdb/config/i386/tm-fbsd.h @@ -24,6 +24,10 @@ #define HAVE_I387_REGS #include "i386/tm-i386.h" +#ifdef HAVE_SYS_PARAM_H +#include +#endif + /* FreeBSD/ELF uses stabs-in-ELF with the DWARF register numbering scheme by default, so we must redefine STAB_REG_TO_REGNUM. This messes up the floating-point registers for a.out, but there is not diff --git a/contrib/gdb/gdb/doc/GDBvn.texi b/contrib/gdb/gdb/doc/GDBvn.texi index fd722bde8f0e..4cd0e3b9f010 100644 --- a/contrib/gdb/gdb/doc/GDBvn.texi +++ b/contrib/gdb/gdb/doc/GDBvn.texi @@ -1 +1 @@ -@set GDBVN 4.18 +@set GDBVN 5.2.1 diff --git a/contrib/gdb/gdb/dwarf2cfi.c b/contrib/gdb/gdb/dwarf2cfi.c index 783d1c014e0e..f0b1e844946a 100644 --- a/contrib/gdb/gdb/dwarf2cfi.c +++ b/contrib/gdb/gdb/dwarf2cfi.c @@ -34,7 +34,7 @@ Frame Descriptors. */ struct cie_unit { - /* Offset of this unit in dwarf_frame_buffer. */ + /* Offset of this unit in .debug_frame or .eh_frame. */ ULONGEST offset; /* A null-terminated string that identifies the augmentation to this CIE or @@ -176,6 +176,15 @@ struct frame_state struct objfile *objfile; }; +enum ptr_encoding +{ + PE_absptr = DW_EH_PE_absptr, + PE_pcrel = DW_EH_PE_pcrel, + PE_textrel = DW_EH_PE_textrel, + PE_datarel = DW_EH_PE_datarel, + PE_funcrel = DW_EH_PE_funcrel +}; + #define UNWIND_CONTEXT(fi) ((struct context *) (fi->context)) @@ -188,8 +197,6 @@ extern file_ptr dwarf_frame_offset; extern unsigned int dwarf_frame_size; extern file_ptr dwarf_eh_frame_offset; extern unsigned int dwarf_eh_frame_size; - -static char *dwarf_frame_buffer; extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offset, @@ -201,26 +208,28 @@ static void fde_chunks_need_space (); static struct context *context_alloc (); static struct frame_state *frame_state_alloc (); +static void unwind_tmp_obstack_init (); static void unwind_tmp_obstack_free (); static void context_cpy (struct context *dst, struct context *src); -static unsigned int read_1u (bfd *abfd, char **p); -static int read_1s (bfd *abfd, char **p); -static unsigned int read_2u (bfd *abfd, char **p); -static int read_2s (bfd *abfd, char **p); -static unsigned int read_4u (bfd *abfd, char **p); -static int read_4s (bfd *abfd, char **p); -static ULONGEST read_8u (bfd *abfd, char **p); -static LONGEST read_8s (bfd *abfd, char **p); +static unsigned int read_1u (bfd * abfd, char **p); +static int read_1s (bfd * abfd, char **p); +static unsigned int read_2u (bfd * abfd, char **p); +static int read_2s (bfd * abfd, char **p); +static unsigned int read_4u (bfd * abfd, char **p); +static int read_4s (bfd * abfd, char **p); +static ULONGEST read_8u (bfd * abfd, char **p); +static LONGEST read_8s (bfd * abfd, char **p); -static ULONGEST read_uleb128 (bfd *abfd, char **p); -static LONGEST read_sleb128 (bfd *abfd, char **p); -static CORE_ADDR read_pointer (bfd *abfd, char **p); -static CORE_ADDR read_encoded_pointer (bfd *abfd, char **p, +static ULONGEST read_uleb128 (bfd * abfd, char **p); +static LONGEST read_sleb128 (bfd * abfd, char **p); +static CORE_ADDR read_pointer (bfd * abfd, char **p); +static CORE_ADDR read_encoded_pointer (bfd * abfd, char **p, unsigned char encoding); +static enum ptr_encoding pointer_encoding (unsigned char encoding); -static LONGEST read_initial_length (bfd *abfd, char *buf, int *bytes_read); -static ULONGEST read_length (bfd *abfd, char *buf, int *bytes_read, +static LONGEST read_initial_length (bfd * abfd, char *buf, int *bytes_read); +static ULONGEST read_length (bfd * abfd, char *buf, int *bytes_read, int dwarf64); static int is_cie (ULONGEST cie_id, int dwarf64); @@ -235,11 +244,12 @@ static void frame_state_for (struct context *context, struct frame_state *fs); static void get_reg (char *reg, struct context *context, int regnum); static CORE_ADDR execute_stack_op (struct objfile *objfile, char *op_ptr, char *op_end, - struct context *context, CORE_ADDR initial); + struct context *context, + CORE_ADDR initial); static void update_context (struct context *context, struct frame_state *fs, int chain); - + /* Memory allocation functions. */ static struct fde_unit * fde_unit_alloc (void) @@ -301,17 +311,23 @@ frame_state_alloc () fs = (struct frame_state *) obstack_alloc (&unwind_tmp_obstack, sizeof (struct frame_state)); memset (fs, 0, sizeof (struct frame_state)); - fs->regs.reg = (struct frame_state_reg *) obstack_alloc (&unwind_tmp_obstack, - regs_size); + fs->regs.reg = + (struct frame_state_reg *) obstack_alloc (&unwind_tmp_obstack, regs_size); memset (fs->regs.reg, 0, regs_size); return fs; } +static void +unwind_tmp_obstack_init () +{ + obstack_init (&unwind_tmp_obstack); +} + static void unwind_tmp_obstack_free () { obstack_free (&unwind_tmp_obstack, NULL); - obstack_init (&unwind_tmp_obstack); + unwind_tmp_obstack_init (); } static void @@ -334,92 +350,92 @@ context_cpy (struct context *dst, struct context *src) dreg = dst->reg; *dst = *src; dst->reg = dreg; - + memcpy (dst->reg, src->reg, regs_size); } static unsigned int -read_1u (bfd *abfd, char **p) +read_1u (bfd * abfd, char **p) { unsigned ret; - ret= bfd_get_8 (abfd, (bfd_byte *) *p); - (*p) ++; + ret = bfd_get_8 (abfd, (bfd_byte *) * p); + (*p)++; return ret; } static int -read_1s (bfd *abfd, char **p) +read_1s (bfd * abfd, char **p) { int ret; - ret= bfd_get_signed_8 (abfd, (bfd_byte *) *p); - (*p) ++; + ret = bfd_get_signed_8 (abfd, (bfd_byte *) * p); + (*p)++; return ret; } static unsigned int -read_2u (bfd *abfd, char **p) +read_2u (bfd * abfd, char **p) { unsigned ret; - ret= bfd_get_16 (abfd, (bfd_byte *) *p); - (*p) ++; + ret = bfd_get_16 (abfd, (bfd_byte *) * p); + (*p)++; return ret; } static int -read_2s (bfd *abfd, char **p) +read_2s (bfd * abfd, char **p) { int ret; - ret= bfd_get_signed_16 (abfd, (bfd_byte *) *p); + ret = bfd_get_signed_16 (abfd, (bfd_byte *) * p); (*p) += 2; return ret; } static unsigned int -read_4u (bfd *abfd, char **p) +read_4u (bfd * abfd, char **p) { unsigned int ret; - ret= bfd_get_32 (abfd, (bfd_byte *) *p); + ret = bfd_get_32 (abfd, (bfd_byte *) * p); (*p) += 4; return ret; } static int -read_4s (bfd *abfd, char **p) +read_4s (bfd * abfd, char **p) { int ret; - ret= bfd_get_signed_32 (abfd, (bfd_byte *) *p); + ret = bfd_get_signed_32 (abfd, (bfd_byte *) * p); (*p) += 4; return ret; } static ULONGEST -read_8u (bfd *abfd, char **p) +read_8u (bfd * abfd, char **p) { ULONGEST ret; - ret = bfd_get_64 (abfd, (bfd_byte *) *p); + ret = bfd_get_64 (abfd, (bfd_byte *) * p); (*p) += 8; return ret; } static LONGEST -read_8s (bfd *abfd, char **p) +read_8s (bfd * abfd, char **p) { LONGEST ret; - ret = bfd_get_signed_64 (abfd, (bfd_byte *) *p); + ret = bfd_get_signed_64 (abfd, (bfd_byte *) * p); (*p) += 8; return ret; } static ULONGEST -read_uleb128 (bfd *abfd, char **p) +read_uleb128 (bfd * abfd, char **p) { ULONGEST ret; int i, shift; @@ -430,8 +446,8 @@ read_uleb128 (bfd *abfd, char **p) i = 0; while (1) { - byte = bfd_get_8 (abfd, (bfd_byte *) *p); - (*p) ++; + byte = bfd_get_8 (abfd, (bfd_byte *) * p); + (*p)++; ret |= ((unsigned long) (byte & 127) << shift); if ((byte & 128) == 0) { @@ -443,7 +459,7 @@ read_uleb128 (bfd *abfd, char **p) } static LONGEST -read_sleb128 (bfd *abfd, char **p) +read_sleb128 (bfd * abfd, char **p) { LONGEST ret; int i, shift, size, num_read; @@ -456,8 +472,8 @@ read_sleb128 (bfd *abfd, char **p) i = 0; while (1) { - byte = bfd_get_8 (abfd, (bfd_byte *) *p); - (*p) ++; + byte = bfd_get_8 (abfd, (bfd_byte *) * p); + (*p)++; ret |= ((long) (byte & 127) << shift); shift += 7; if ((byte & 128) == 0) @@ -473,7 +489,7 @@ read_sleb128 (bfd *abfd, char **p) } static CORE_ADDR -read_pointer (bfd *abfd, char **p) +read_pointer (bfd * abfd, char **p) { switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT) { @@ -486,8 +502,11 @@ read_pointer (bfd *abfd, char **p) } } +/* This functions only reads appropriate amount of data from *p + * and returns the resulting value. Calling function must handle + * different encoding possibilities itself! */ static CORE_ADDR -read_encoded_pointer (bfd *abfd, char **p, unsigned char encoding) +read_encoded_pointer (bfd * abfd, char **p, unsigned char encoding) { CORE_ADDR ret; @@ -529,22 +548,33 @@ read_encoded_pointer (bfd *abfd, char **p, unsigned char encoding) "read_encoded_pointer: unknown pointer encoding"); } - if (ret != 0) - switch (encoding & 0xf0) - { - case DW_EH_PE_absptr: - break; - case DW_EH_PE_pcrel: - ret += (CORE_ADDR) *p; - break; - case DW_EH_PE_textrel: - case DW_EH_PE_datarel: - case DW_EH_PE_funcrel: - default: - internal_error (__FILE__, __LINE__, - "read_encoded_pointer: unknown pointer encoding"); - } + return ret; +} +/* Variable 'encoding' carries 3 different flags: + * - encoding & 0x0f : size of the address (handled in read_encoded_pointer()) + * - encoding & 0x70 : type (absolute, relative, ...) + * - encoding & 0x80 : indirect flag (DW_EH_PE_indirect == 0x80). */ +enum ptr_encoding +pointer_encoding (unsigned char encoding) +{ + int ret; + + if (encoding & DW_EH_PE_indirect) + warning ("CFI: Unsupported pointer encoding: DW_EH_PE_indirect"); + + switch (encoding & 0x70) + { + case DW_EH_PE_absptr: + case DW_EH_PE_pcrel: + case DW_EH_PE_textrel: + case DW_EH_PE_datarel: + case DW_EH_PE_funcrel: + ret = encoding & 0x70; + break; + default: + internal_error (__FILE__, __LINE__, "CFI: unknown pointer encoding"); + } return ret; } @@ -584,8 +614,8 @@ read_length (bfd * abfd, char *buf, int *bytes_read, int dwarf64) } static void -execute_cfa_program ( struct objfile *objfile, char *insn_ptr, char *insn_end, - struct context *context, struct frame_state *fs) +execute_cfa_program (struct objfile *objfile, char *insn_ptr, char *insn_end, + struct context *context, struct frame_state *fs) { struct frame_state_regs *unused_rs = NULL; @@ -604,7 +634,7 @@ execute_cfa_program ( struct objfile *objfile, char *insn_ptr, char *insn_end, { reg = insn & 0x3f; uoffset = read_uleb128 (objfile->obfd, &insn_ptr); - offset = (long) uoffset * fs->data_align; + offset = (long) uoffset *fs->data_align; fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; } @@ -619,6 +649,10 @@ execute_cfa_program ( struct objfile *objfile, char *insn_ptr, char *insn_end, case DW_CFA_set_loc: fs->pc = read_encoded_pointer (objfile->obfd, &insn_ptr, fs->addr_encoding); + + if (pointer_encoding (fs->addr_encoding) != PE_absptr) + warning ("CFI: DW_CFA_set_loc uses relative addressing"); + break; case DW_CFA_advance_loc1: @@ -806,13 +840,13 @@ frame_state_for (struct context *context, struct frame_state *fs) if (fde == NULL) return; - + fs->pc = fde->initial_location; if (fde->cie_ptr) - { + { cie = fde->cie_ptr; - + fs->code_align = cie->code_align; fs->data_align = cie->data_align; fs->retaddr_column = cie->ra; @@ -823,11 +857,10 @@ frame_state_for (struct context *context, struct frame_state *fs) cie->data + cie->data_length, context, fs); execute_cfa_program (cie->objfile, fde->data, fde->data + fde->data_length, context, fs); - } + } else - internal_error (__FILE__, __LINE__, - "%s(): Internal error: fde->cie_ptr==NULL !", - __func__); + internal_error (__FILE__, __LINE__, + "%s(): Internal error: fde->cie_ptr==NULL !", "?func?"); } static void @@ -854,8 +887,7 @@ get_reg (char *reg, struct context *context, int regnum) REGISTER_RAW_SIZE (regnum)); break; default: - internal_error (__FILE__, __LINE__, - "get_reg: unknown register rule"); + internal_error (__FILE__, __LINE__, "get_reg: unknown register rule"); } } @@ -1208,8 +1240,8 @@ execute_stack_op (struct objfile *objfile, case DW_OP_ne: result = (LONGEST) first != (LONGEST) second; break; - default: /* This label is here just to avoid warning. */ - break; + default: /* This label is here just to avoid warning. */ + break; } } break; @@ -1255,8 +1287,11 @@ update_context (struct context *context, struct frame_state *fs, int chain) CORE_ADDR cfa; long i; + unwind_tmp_obstack_init (); + orig_context = context_alloc (); context_cpy (orig_context, context); + /* Compute this frame's CFA. */ switch (fs->cfa_how) { @@ -1267,9 +1302,9 @@ update_context (struct context *context, struct frame_state *fs, int chain) case CFA_EXP: /* ??? No way of knowing what register number is the stack pointer - to do the same sort of handling as above. Assume that if the - CFA calculation is so complicated as to require a stack program - that this will not be a problem. */ + to do the same sort of handling as above. Assume that if the + CFA calculation is so complicated as to require a stack program + that this will not be a problem. */ { char *exp = fs->cfa_exp; ULONGEST len; @@ -1326,7 +1361,7 @@ update_context (struct context *context, struct frame_state *fs, int chain) orig_context->reg[fs->regs.reg[i].loc.reg].loc.addr; default: internal_error (__FILE__, __LINE__, - "%s: unknown register rule", __func__); + "%s: unknown register rule", "?func?"); } break; case REG_SAVED_EXP: @@ -1344,7 +1379,7 @@ update_context (struct context *context, struct frame_state *fs, int chain) break; default: internal_error (__FILE__, __LINE__, - "%s: unknown register rule", __func__); + "%s: unknown register rule", "?func?"); } get_reg ((char *) &context->ra, context, fs->retaddr_column); unwind_tmp_obstack_free (); @@ -1371,39 +1406,46 @@ compare_fde_unit (const void *a, const void *b) } /* Build the cie_chunks and fde_chunks tables from informations - in .debug_frame section. */ -void -dwarf2_build_frame_info (struct objfile *objfile) + found in .debug_frame and .eh_frame sections. */ +/* We can handle both of these sections almost in the same way, however there + are some exceptions: + - CIE ID is -1 in debug_frame, but 0 in eh_frame + - eh_frame may contain some more information that are used only by gcc + (eg. personality pointer, LSDA pointer, ...). Most of them we can ignore. + - In debug_frame FDE's item cie_id contains offset of it's parent CIE. + In eh_frame FDE's item cie_id is a relative pointer to the parent CIE. + Anyway we don't need to bother with this, because we are smart enough + to keep the pointer to the parent CIE of oncomming FDEs in 'last_cie'. + - Although debug_frame items can contain Augmentation as well as + eh_frame ones, I have never seen them non-empty. Thus only in eh_frame + we can encounter for example non-absolute pointers (Aug. 'R'). + -- mludvig */ +static void +parse_frame_info (struct objfile *objfile, file_ptr frame_offset, + unsigned int frame_size, int eh_frame) { bfd *abfd = objfile->obfd; + asection *curr_section_ptr; char *start = NULL; char *end = NULL; - int from_eh = 0; + char *frame_buffer = NULL; + char *curr_section_name, *aug_data; + struct cie_unit *last_cie = NULL; + int last_dup_fde = 0; + int aug_len, i; + CORE_ADDR curr_section_vma = 0; - obstack_init (&unwind_tmp_obstack); + unwind_tmp_obstack_init (); - dwarf_frame_buffer = 0; + frame_buffer = dwarf2_read_section (objfile, frame_offset, frame_size); - if (dwarf_frame_offset) - { - dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_frame_offset, - dwarf_frame_size); + start = frame_buffer; + end = frame_buffer + frame_size; - start = dwarf_frame_buffer; - end = dwarf_frame_buffer + dwarf_frame_size; - } - else if (dwarf_eh_frame_offset) - { - dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_eh_frame_offset, - dwarf_eh_frame_size); - - start = dwarf_frame_buffer; - end = dwarf_frame_buffer + dwarf_eh_frame_size; - - from_eh = 1; - } + curr_section_name = eh_frame ? ".eh_frame" : ".debug_frame"; + curr_section_ptr = bfd_get_section_by_name (abfd, curr_section_name); + if (curr_section_ptr) + curr_section_vma = curr_section_ptr->vma; if (start) { @@ -1411,9 +1453,8 @@ dwarf2_build_frame_info (struct objfile *objfile) { unsigned long length; ULONGEST cie_id; - ULONGEST unit_offset = start - dwarf_frame_buffer; - int bytes_read; - int dwarf64; + ULONGEST unit_offset = start - frame_buffer; + int bytes_read, dwarf64; char *block_end; length = read_initial_length (abfd, start, &bytes_read); @@ -1421,10 +1462,16 @@ dwarf2_build_frame_info (struct objfile *objfile) dwarf64 = (bytes_read == 12); block_end = start + length; + if (length == 0) + { + start = block_end; + continue; + } + cie_id = read_length (abfd, start, &bytes_read, dwarf64); start += bytes_read; - if ((from_eh && cie_id == 0) || is_cie (cie_id, dwarf64)) + if ((eh_frame && cie_id == 0) || is_cie (cie_id, dwarf64)) { struct cie_unit *cie = cie_unit_alloc (); char *aug; @@ -1440,84 +1487,186 @@ dwarf2_build_frame_info (struct objfile *objfile) start++; /* version */ cie->augmentation = aug = start; - while (*start) - start++; - start++; /* skip past NUL */ + while (*start++); /* Skips last NULL as well */ cie->code_align = read_uleb128 (abfd, &start); cie->data_align = read_sleb128 (abfd, &start); cie->ra = read_1u (abfd, &start); + /* Augmentation: + z Indicates that a uleb128 is present to size the + augmentation section. + L Indicates the encoding (and thus presence) of + an LSDA pointer in the FDE augmentation. + R Indicates a non-default pointer encoding for + FDE code pointers. + P Indicates the presence of an encoding + language + personality routine in the CIE augmentation. + + [This info comes from GCC's dwarf2out.c] + */ if (*aug == 'z') { - int xtra = read_uleb128 (abfd, &start); - start += xtra; + aug_len = read_uleb128 (abfd, &start); + aug_data = start; + start += aug_len; ++aug; } + cie->data = start; + cie->data_length = block_end - cie->data; + while (*aug != '\0') { if (aug[0] == 'e' && aug[1] == 'h') { - start += sizeof (void *); - aug += 2; + aug_data += sizeof (void *); + aug++; } else if (aug[0] == 'R') - { - cie->addr_encoding = *start++; - aug += 1; - } + cie->addr_encoding = *aug_data++; else if (aug[0] == 'P') { - CORE_ADDR ptr; - ptr = read_encoded_pointer (abfd, &start, - cie->addr_encoding); - aug += 1; + CORE_ADDR pers_addr; + int pers_addr_enc; + + pers_addr_enc = *aug_data++; + /* We don't need pers_addr value and so we + don't care about it's encoding. */ + pers_addr = read_encoded_pointer (abfd, &aug_data, + pers_addr_enc); + } + else if (aug[0] == 'L' && eh_frame) + { + int lsda_addr_enc; + + /* Perhaps we should save this to CIE for later use? + Do we need it for something in GDB? */ + lsda_addr_enc = *aug_data++; } else - warning ("%s(): unknown augmentation", __func__); + warning ("CFI warning: unknown augmentation \"%c\"" + " in \"%s\" of\n" + "\t%s", aug[0], curr_section_name, + objfile->name); + aug++; } - cie->data = start; - cie->data_length = block_end - start; + last_cie = cie; } else { struct fde_unit *fde; struct cie_unit *cie; + int dup = 0; + CORE_ADDR init_loc; - fde_chunks_need_space (); - fde = fde_unit_alloc (); - - fde_chunks.array[fde_chunks.elems++] = fde; - - fde->initial_location = read_pointer (abfd, &start) - + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - fde->address_range = read_pointer (abfd, &start); - - cie = cie_chunks; - while(cie) - { - if (cie->objfile == objfile) + /* We assume that debug_frame is in order + CIE,FDE,CIE,FDE,FDE,... and thus the CIE for this FDE + should be stored in last_cie pointer. If not, we'll + try to find it by the older way. */ + if (last_cie) + cie = last_cie; + else { - if (from_eh && (cie->offset == (unit_offset + bytes_read - cie_id))) - break; - if (!from_eh && (cie->offset == cie_id)) - break; + warning ("CFI: last_cie == NULL. " + "Perhaps a malformed %s section in '%s'...?\n", + curr_section_name, objfile->name); + + cie = cie_chunks; + while (cie) + { + if (cie->objfile == objfile) + { + if (eh_frame && + (cie->offset == + (unit_offset + bytes_read - cie_id))) + break; + if (!eh_frame && (cie->offset == cie_id)) + break; + } + + cie = cie->next; + } + if (!cie) + error ("CFI: can't find CIE pointer"); } - cie = cie->next; - } - - if (!cie) - error ("%s(): can't find CIE pointer", __func__); - fde->cie_ptr = cie; + init_loc = read_encoded_pointer (abfd, &start, + cie->addr_encoding); - if (cie->augmentation[0] == 'z') - read_uleb128 (abfd, &start); + switch (pointer_encoding (cie->addr_encoding)) + { + case PE_absptr: + break; + case PE_pcrel: + /* start-frame_buffer gives offset from + the beginning of actual section. */ + init_loc += curr_section_vma + start - frame_buffer; + break; + default: + warning ("CFI: Unsupported pointer encoding\n"); + } - fde->data = start; - fde->data_length = block_end - start; + /* For relocatable objects we must add an offset telling + where the section is actually mapped in the memory. */ + init_loc += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); + + /* If we have both .debug_frame and .eh_frame present in + a file, we must eliminate duplicate FDEs. For now we'll + run through all entries in fde_chunks and check it one + by one. Perhaps in the future we can implement a faster + searching algorithm. */ + /* eh_frame==2 indicates, that this file has an already + parsed .debug_frame too. When eh_frame==1 it means, that no + .debug_frame is present and thus we don't need to check for + duplicities. eh_frame==0 means, that we parse .debug_frame + and don't need to care about duplicate FDEs, because + .debug_frame is parsed first. */ + if (eh_frame == 2) + for (i = 0; eh_frame == 2 && i < fde_chunks.elems; i++) + { + /* We assume that FDEs in .debug_frame and .eh_frame + have the same order (if they are present, of course). + If we find a duplicate entry for one FDE and save + it's index to last_dup_fde it's very likely, that + we'll find an entry for the following FDE right after + the previous one. Thus in many cases we'll run this + loop only once. */ + last_dup_fde = (last_dup_fde + i) % fde_chunks.elems; + if (fde_chunks.array[last_dup_fde]->initial_location + == init_loc) + { + dup = 1; + break; + } + } + + /* Allocate a new entry only if this FDE isn't a duplicate of + something we have already seen. */ + if (!dup) + { + fde_chunks_need_space (); + fde = fde_unit_alloc (); + + fde_chunks.array[fde_chunks.elems++] = fde; + + fde->initial_location = init_loc; + fde->address_range = read_encoded_pointer (abfd, &start, + cie-> + addr_encoding); + + fde->cie_ptr = cie; + + /* Here we intentionally ignore augmentation data + from FDE, because we don't need them. */ + if (cie->augmentation[0] == 'z') + start += read_uleb128 (abfd, &start); + + fde->data = start; + fde->data_length = block_end - start; + } } start = block_end; } @@ -1525,7 +1674,30 @@ dwarf2_build_frame_info (struct objfile *objfile) sizeof (struct fde_unit *), compare_fde_unit); } } - + +/* We must parse both .debug_frame section and .eh_frame because + * not all frames must be present in both of these sections. */ +void +dwarf2_build_frame_info (struct objfile *objfile) +{ + int after_debug_frame = 0; + + /* If we have .debug_frame then the parser is called with + eh_frame==0 for .debug_frame and eh_frame==2 for .eh_frame, + otherwise it's only called once for .eh_frame with argument + eh_frame==1. */ + + if (dwarf_frame_offset) + { + parse_frame_info (objfile, dwarf_frame_offset, + dwarf_frame_size, 0 /* = debug_frame */ ); + after_debug_frame = 1; + } + + if (dwarf_eh_frame_offset) + parse_frame_info (objfile, dwarf_eh_frame_offset, dwarf_eh_frame_size, + 1 /* = eh_frame */ + after_debug_frame); +} /* Return the frame address. */ CORE_ADDR @@ -1535,6 +1707,8 @@ cfi_read_fp () struct frame_state *fs; CORE_ADDR cfa; + unwind_tmp_obstack_init (); + context = context_alloc (); fs = frame_state_alloc (); @@ -1544,7 +1718,9 @@ cfi_read_fp () update_context (context, fs, 0); cfa = context->cfa; + unwind_tmp_obstack_free (); + return cfa; } @@ -1556,6 +1732,8 @@ cfi_write_fp (CORE_ADDR val) struct context *context; struct frame_state *fs; + unwind_tmp_obstack_init (); + context = context_alloc (); fs = frame_state_alloc (); @@ -1603,6 +1781,8 @@ cfi_frame_chain (struct frame_info *fi) struct frame_state *fs; CORE_ADDR cfa; + unwind_tmp_obstack_init (); + context = context_alloc (); fs = frame_state_alloc (); context_cpy (context, UNWIND_CONTEXT (fi)); @@ -1619,7 +1799,7 @@ cfi_frame_chain (struct frame_info *fi) cfa = context->cfa; unwind_tmp_obstack_free (); - + return cfa; } @@ -1639,6 +1819,8 @@ cfi_init_extra_frame_info (int fromleaf, struct frame_info *fi) { struct frame_state *fs; + unwind_tmp_obstack_init (); + fs = frame_state_alloc (); fi->context = frame_obstack_alloc (sizeof (struct context)); UNWIND_CONTEXT (fi)->reg = @@ -1658,6 +1840,7 @@ cfi_init_extra_frame_info (int fromleaf, struct frame_info *fi) frame_state_for (UNWIND_CONTEXT (fi), fs); update_context (UNWIND_CONTEXT (fi), fs, 0); } + unwind_tmp_obstack_free (); } @@ -1678,7 +1861,7 @@ cfi_get_ra (struct frame_info *fi) void cfi_get_saved_register (char *raw_buffer, int *optimized, - CORE_ADDR * addrp, + CORE_ADDR *addrp, struct frame_info *frame, int regnum, enum lval_type *lval) { @@ -1765,6 +1948,8 @@ cfi_virtual_frame_pointer (CORE_ADDR pc, int *frame_reg, struct context *context; struct frame_state *fs; + unwind_tmp_obstack_init (); + context = context_alloc (); fs = frame_state_alloc (); diff --git a/contrib/gdb/gdb/gdbserver/gdbreplay.c b/contrib/gdb/gdb/gdbserver/gdbreplay.c index dce4079e3f18..8c57906ea076 100644 --- a/contrib/gdb/gdb/gdbserver/gdbreplay.c +++ b/contrib/gdb/gdb/gdbserver/gdbreplay.c @@ -31,6 +31,16 @@ #include #include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + /* Sort of a hack... */ #define EOL (EOF - 1) @@ -40,7 +50,7 @@ static int remote_desc; as the file name for which the error was encountered. Then return to command level. */ -void +static void perror_with_name (char *string) { #ifndef STDC_HEADERS @@ -71,7 +81,7 @@ sync_error (FILE *fp, char *desc, int expect, int got) exit (1); } -void +static void remote_close (void) { close (remote_desc); @@ -80,10 +90,12 @@ remote_close (void) /* Open a connection to a remote debugger. NAME is the filename used for communication. */ -void +static void remote_open (char *name) { +#ifndef HAVE_STRING_H extern char *strchr (); +#endif if (!strchr (name, ':')) { @@ -230,7 +242,7 @@ logchar (FILE *fp) /* Accept input from gdb and match with chars from fp (after skipping one blank) up until a \n is read from fp (which is not matched) */ -void +static void expect (FILE *fp) { int fromlog; @@ -261,7 +273,7 @@ expect (FILE *fp) /* Play data back to gdb from fp (after skipping leading blank) up until a \n is read from fp (which is discarded and not sent to gdb). */ -void +static void play (FILE *fp) { int fromlog; diff --git a/contrib/gdb/gdb/gdbserver/linux-mips-low.c b/contrib/gdb/gdb/gdbserver/linux-mips-low.c new file mode 100644 index 000000000000..a9114d3fb649 --- /dev/null +++ b/contrib/gdb/gdb/gdbserver/linux-mips-low.c @@ -0,0 +1,97 @@ +/* GNU/Linux/MIPS specific low level interface, for the remote server for GDB. + Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002 + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "server.h" +#include "linux-low.h" + +#ifdef HAVE_SYS_REG_H +#include +#endif + +int num_regs = 90; + +#include + +/* Return the ptrace ``address'' of register REGNO. */ + +/* Matches mips_generic32_regs */ +int regmap[] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + + -1, MMLO, MMHI, BADVADDR, CAUSE, PC, + + FPR_BASE, FPR_BASE + 1, FPR_BASE + 2, FPR_BASE + 3, + FPR_BASE + 4, FPR_BASE + 5, FPR_BASE + 6, FPR_BASE + 7, + FPR_BASE + 8, FPR_BASE + 8, FPR_BASE + 10, FPR_BASE + 11, + FPR_BASE + 12, FPR_BASE + 13, FPR_BASE + 14, FPR_BASE + 15, + FPR_BASE + 16, FPR_BASE + 17, FPR_BASE + 18, FPR_BASE + 19, + FPR_BASE + 20, FPR_BASE + 21, FPR_BASE + 22, FPR_BASE + 23, + FPR_BASE + 24, FPR_BASE + 25, FPR_BASE + 26, FPR_BASE + 27, + FPR_BASE + 28, FPR_BASE + 29, FPR_BASE + 30, FPR_BASE + 31, + FPC_CSR, FPC_EIR, + + -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +/* From mips-linux-nat.c. */ + +/* Pseudo registers can not be read. ptrace does not provide a way to + read (or set) PS_REGNUM, and there's no point in reading or setting + ZERO_REGNUM. We also can not set BADVADDR, CAUSE, or FCRIR via + ptrace(). */ + +int +cannot_fetch_register (int regno) +{ + if (regmap[regno] == -1) + return 1; + + if (find_regno ("zero") == regno) + return 1; + + return 0; +} + +int +cannot_store_register (int regno) +{ + if (regmap[regno] == -1) + return 1; + + if (find_regno ("zero") == regno) + return 1; + + if (find_regno ("cause") == regno) + return 1; + + if (find_regno ("bad") == regno) + return 1; + + if (find_regno ("fir") == regno) + return 1; + + return 0; +} diff --git a/contrib/gdb/gdb/gdbserver/linux-ppc-low.c b/contrib/gdb/gdb/gdbserver/linux-ppc-low.c new file mode 100644 index 000000000000..dcefa59a677d --- /dev/null +++ b/contrib/gdb/gdb/gdbserver/linux-ppc-low.c @@ -0,0 +1,62 @@ +/* GNU/Linux/PowerPC specific low level interface, for the remote server for + GDB. + Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002 + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "server.h" +#include "linux-low.h" + +#include + +int num_regs = 71; + +/* Currently, don't check/send MQ. */ +int regmap[] = + {PT_R0 * 4, PT_R1 * 4, PT_R2 * 4, PT_R3 * 4, + PT_R4 * 4, PT_R5 * 4, PT_R6 * 4, PT_R7 * 4, + PT_R8 * 4, PT_R9 * 4, PT_R10 * 4, PT_R11 * 4, + PT_R12 * 4, PT_R13 * 4, PT_R14 * 4, PT_R15 * 4, + PT_R16 * 4, PT_R17 * 4, PT_R18 * 4, PT_R19 * 4, + PT_R20 * 4, PT_R21 * 4, PT_R22 * 4, PT_R23 * 4, + PT_R24 * 4, PT_R25 * 4, PT_R26 * 4, PT_R27 * 4, + PT_R28 * 4, PT_R29 * 4, PT_R30 * 4, PT_R31 * 4, + PT_FPR0*4, PT_FPR0*4 + 8, PT_FPR0*4+16, PT_FPR0*4+24, + PT_FPR0*4+32, PT_FPR0*4+40, PT_FPR0*4+48, PT_FPR0*4+56, + PT_FPR0*4+64, PT_FPR0*4+72, PT_FPR0*4+80, PT_FPR0*4+88, + PT_FPR0*4+96, PT_FPR0*4+104, PT_FPR0*4+112, PT_FPR0*4+120, + PT_FPR0*4+128, PT_FPR0*4+136, PT_FPR0*4+144, PT_FPR0*4+152, + PT_FPR0*4+160, PT_FPR0*4+168, PT_FPR0*4+176, PT_FPR0*4+184, + PT_FPR0*4+192, PT_FPR0*4+200, PT_FPR0*4+208, PT_FPR0*4+216, + PT_FPR0*4+224, PT_FPR0*4+232, PT_FPR0*4+240, PT_FPR0*4+248, + PT_NIP * 4, PT_MSR * 4, PT_CCR * 4, PT_LNK * 4, + PT_CTR * 4, PT_XER * 4, -1, }; + +int +cannot_store_register (int regno) +{ + return 0; +} + +int +cannot_fetch_register (int regno) +{ + return 0; +} + diff --git a/contrib/gdb/gdb/i386-nat.c b/contrib/gdb/gdb/i386-nat.c index adf220bba730..53a81a463eb1 100644 --- a/contrib/gdb/gdb/i386-nat.c +++ b/contrib/gdb/gdb/i386-nat.c @@ -230,6 +230,14 @@ i386_cleanup_dregs (void) dr_status_mirror = 0; } +/* Reset all debug registers at each new startup + to avoid missing watchpoints after restart. */ +void +child_post_startup_inferior (ptid_t ptid) +{ + i386_cleanup_dregs (); +} + /* Print the values of the mirrored debug registers. This is called when maint_show_dr is non-zero. To set that up, type "maint show-debug-regs" at GDB's prompt. */ diff --git a/contrib/gdb/gdb/objfiles.h b/contrib/gdb/gdb/objfiles.h index 992ae71e47f2..d1746a970aca 100644 --- a/contrib/gdb/gdb/objfiles.h +++ b/contrib/gdb/gdb/objfiles.h @@ -22,6 +22,8 @@ #if !defined (OBJFILES_H) #define OBJFILES_H +#include "bcache.h" + /* This structure maintains information on a per-objfile basis about the "entry point" of the objfile, and the scope within which the entry point exists. It is possible that gdb will see more than one objfile that is diff --git a/contrib/gdb/gdb/regformats/reg-mips.dat b/contrib/gdb/gdb/regformats/reg-mips.dat new file mode 100644 index 000000000000..7a7c8086e94e --- /dev/null +++ b/contrib/gdb/gdb/regformats/reg-mips.dat @@ -0,0 +1,112 @@ +name:mips +expedite:pc,sp +32:zero +32:at +32:v0 +32:v1 + +32:a0 +32:a1 +32:a2 +32:a3 + +32:t0 +32:t1 +32:t2 +32:t3 + +32:t4 +32:t5 +32:t6 +32:t7 + +32:s0 +32:s1 +32:s2 +32:s3 + +32:s4 +32:s5 +32:s6 +32:s7 + +32:t8 +32:t9 +32:k0 +32:k1 + +32:gp +32:sp +32:s8 +32:ra + +32:sr +32:lo +32:hi +32:bad + +32:cause +32:pc + +32:f0 +32:f1 +32:f2 +32:f3 + +32:f4 +32:f5 +32:f6 +32:f7 + +32:f8 +32:f9 +32:f10 +32:f11 + +32:f12 +32:f13 +32:f14 +32:f15 + +32:f16 +32:f17 +32:f18 +32:f19 + +32:f20 +32:f21 +32:f22 +32:f23 + +32:f24 +32:f25 +32:f26 +32:f27 + +32:f28 +32:f29 +32:f30 +32:f31 + +32:fsr +32:fir + +32:fp +32: + +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: diff --git a/contrib/gdb/gdb/regformats/reg-sh.dat b/contrib/gdb/gdb/regformats/reg-sh.dat new file mode 100644 index 000000000000..d670b46765b0 --- /dev/null +++ b/contrib/gdb/gdb/regformats/reg-sh.dat @@ -0,0 +1,62 @@ +name:sh +expedite:pc,r14,r15 +32:r0 +32:r1 +32:r2 +32:r3 +32:r4 +32:r5 +32:r6 +32:r7 +32:r8 +32:r9 +32:r10 +32:r11 +32:r12 +32:r13 +32:r14 +32:r15 +32:pc +32:pr +32:gbr +32:vbr +32:mach +32:macl +32:sr +32:fpul +32:fpscr +32:fr0 +32:fr1 +32:fr2 +32:fr3 +32:fr4 +32:fr5 +32:fr6 +32:fr7 +32:fr8 +32:fr9 +32:fr10 +32:fr11 +32:fr12 +32:fr13 +32:fr14 +32:fr15 + +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: +32: diff --git a/contrib/gdb/gdb/symtab.h b/contrib/gdb/gdb/symtab.h index 75470e60f755..5c11e75cada4 100644 --- a/contrib/gdb/gdb/symtab.h +++ b/contrib/gdb/gdb/symtab.h @@ -28,7 +28,6 @@ #include "obstack.h" #define obstack_chunk_alloc xmalloc #define obstack_chunk_free xfree -#include "bcache.h" /* Don't do this; it means that if some .o's are compiled with GNU C and some are not (easy to do accidentally the way we configure diff --git a/contrib/gdb/gdb/version.in b/contrib/gdb/gdb/version.in index 954676d53055..26d99a283f21 100644 --- a/contrib/gdb/gdb/version.in +++ b/contrib/gdb/gdb/version.in @@ -1 +1 @@ -5.2.0_2002-06-27-cvs +5.2.1 diff --git a/contrib/gdb/gdb/x86-64-linux-nat.c b/contrib/gdb/gdb/x86-64-linux-nat.c index fd7057275244..7749b4151148 100644 --- a/contrib/gdb/gdb/x86-64-linux-nat.c +++ b/contrib/gdb/gdb/x86-64-linux-nat.c @@ -25,7 +25,6 @@ #include "inferior.h" #include "gdbcore.h" #include "regcache.h" -#include "i387-nat.h" #include "gdb_assert.h" #include "x86-64-tdep.h" @@ -158,7 +157,7 @@ fill_gregset (elf_gregset_t * gregsetp, int regno) for (i = 0; i < x86_64_num_gregs; i++) if ((regno == -1 || regno == i)) - read_register_gen (i, regp + x86_64_regmap[i]); + read_register_gen (i, (char *) (regp + x86_64_regmap[i])); } /* Fetch all general-purpose registers from process/thread TID and @@ -195,23 +194,73 @@ store_regs (int tid, int regno) /* Transfering floating-point registers between GDB, inferiors and cores. */ -/* Fill GDB's register array with the floating-point register values in - *FPREGSETP. */ - -void -supply_fpregset (elf_fpregset_t * fpregsetp) +static void * +x86_64_fxsave_offset (elf_fpregset_t * fxsave, int regnum) { - i387_supply_fxsave ((char *) fpregsetp); + const char *reg_name; + int reg_index; + + gdb_assert (x86_64_num_gregs - 1 < regnum && regnum < x86_64_num_regs); + + reg_name = x86_64_register_name (regnum); + + if (reg_name[0] == 's' && reg_name[1] == 't') + { + reg_index = reg_name[2] - '0'; + return &fxsave->st_space[reg_index * 2]; + } + + if (reg_name[0] == 'x' && reg_name[1] == 'm' && reg_name[2] == 'm') + { + reg_index = reg_name[3] - '0'; + return &fxsave->xmm_space[reg_index * 4]; + } + + if (strcmp (reg_name, "mxcsr") == 0) + return &fxsave->mxcsr; + + return NULL; } -/* Fill register REGNO (if it is a floating-point register) in - *FPREGSETP with the value in GDB's register array. If REGNO is -1, - do this for all registers. */ +/* Fill GDB's register array with the floating-point and SSE register + values in *FXSAVE. This function masks off any of the reserved + bits in *FXSAVE. */ void -fill_fpregset (elf_fpregset_t * fpregsetp, int regno) +supply_fpregset (elf_fpregset_t * fxsave) { - i387_fill_fxsave ((char *) fpregsetp, regno); + int i, reg_st0, reg_mxcsr; + + reg_st0 = x86_64_register_number ("st0"); + reg_mxcsr = x86_64_register_number ("mxcsr"); + + gdb_assert (reg_st0 > 0 && reg_mxcsr > reg_st0); + + for (i = reg_st0; i <= reg_mxcsr; i++) + supply_register (i, x86_64_fxsave_offset (fxsave, i)); +} + +/* Fill register REGNUM (if it is a floating-point or SSE register) in + *FXSAVE with the value in GDB's register array. If REGNUM is -1, do + this for all registers. This function doesn't touch any of the + reserved bits in *FXSAVE. */ + +void +fill_fpregset (elf_fpregset_t * fxsave, int regnum) +{ + int i, last_regnum = MXCSR_REGNUM; + void *ptr; + + if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0) + last_regnum = FOP_REGNUM; + + for (i = FP0_REGNUM; i <= last_regnum; i++) + if (regnum == -1 || regnum == i) + { + ptr = x86_64_fxsave_offset (fxsave, i); + if (ptr) + regcache_collect (i, ptr); + } } /* Fetch all floating-point registers from process/thread TID and store @@ -406,12 +455,6 @@ static struct core_fns linux_elf_core_fns = { #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER) #endif -/* Record the value of the debug control register. */ -static long debug_control_mirror; - -/* Record which address associates with which register. */ -static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1]; - /* Return the address of register REGNUM. BLOCKEND is the value of u.u_ar0, which should point to the registers. */ CORE_ADDR @@ -446,4 +489,3 @@ kernel_u_size (void) { return (sizeof (struct user)); } - diff --git a/contrib/gdb/gdb/x86-64-tdep.c b/contrib/gdb/gdb/x86-64-tdep.c index 3ebc1b2594ab..7b6538241d01 100644 --- a/contrib/gdb/gdb/x86-64-tdep.c +++ b/contrib/gdb/gdb/x86-64-tdep.c @@ -28,6 +28,7 @@ #include "arch-utils.h" #include "regcache.h" #include "symfile.h" +#include "objfiles.h" #include "x86-64-tdep.h" #include "dwarf2cfi.h" #include "gdb_assert.h" @@ -37,6 +38,7 @@ #define RDX_REGNUM 3 #define RDI_REGNUM 5 #define EFLAGS_REGNUM 17 +#define ST0_REGNUM 22 #define XMM1_REGNUM 39 struct register_info @@ -49,63 +51,90 @@ struct register_info /* x86_64_register_raw_size_table[i] is the number of bytes of storage in GDB's register array occupied by register i. */ static struct register_info x86_64_register_info_table[] = { - {8, "rax", &builtin_type_int64}, - {8, "rbx", &builtin_type_int64}, - {8, "rcx", &builtin_type_int64}, - {8, "rdx", &builtin_type_int64}, - {8, "rsi", &builtin_type_int64}, - {8, "rdi", &builtin_type_int64}, - {8, "rbp", &builtin_type_void_func_ptr}, - {8, "rsp", &builtin_type_void_func_ptr}, - {8, "r8", &builtin_type_int64}, - {8, "r9", &builtin_type_int64}, - {8, "r10", &builtin_type_int64}, - {8, "r11", &builtin_type_int64}, - {8, "r12", &builtin_type_int64}, - {8, "r13", &builtin_type_int64}, - {8, "r14", &builtin_type_int64}, - {8, "r15", &builtin_type_int64}, - {8, "rip", &builtin_type_void_func_ptr}, - {4, "eflags", &builtin_type_int32}, - {4, "ds", &builtin_type_int32}, - {4, "es", &builtin_type_int32}, - {4, "fs", &builtin_type_int32}, - {4, "gs", &builtin_type_int32}, - {10, "st0", &builtin_type_i387_ext}, - {10, "st1", &builtin_type_i387_ext}, - {10, "st2", &builtin_type_i387_ext}, - {10, "st3", &builtin_type_i387_ext}, - {10, "st4", &builtin_type_i387_ext}, - {10, "st5", &builtin_type_i387_ext}, - {10, "st6", &builtin_type_i387_ext}, - {10, "st7", &builtin_type_i387_ext}, - {4, "fctrl", &builtin_type_int32}, - {4, "fstat", &builtin_type_int32}, - {4, "ftag", &builtin_type_int32}, - {4, "fiseg", &builtin_type_int32}, - {4, "fioff", &builtin_type_int32}, - {4, "foseg", &builtin_type_int32}, - {4, "fooff", &builtin_type_int32}, - {4, "fop", &builtin_type_int32}, - {16, "xmm0", &builtin_type_v4sf}, - {16, "xmm1", &builtin_type_v4sf}, - {16, "xmm2", &builtin_type_v4sf}, - {16, "xmm3", &builtin_type_v4sf}, - {16, "xmm4", &builtin_type_v4sf}, - {16, "xmm5", &builtin_type_v4sf}, - {16, "xmm6", &builtin_type_v4sf}, - {16, "xmm7", &builtin_type_v4sf}, - {16, "xmm8", &builtin_type_v4sf}, - {16, "xmm9", &builtin_type_v4sf}, - {16, "xmm10", &builtin_type_v4sf}, - {16, "xmm11", &builtin_type_v4sf}, - {16, "xmm12", &builtin_type_v4sf}, - {16, "xmm13", &builtin_type_v4sf}, - {16, "xmm14", &builtin_type_v4sf}, - {16, "xmm15", &builtin_type_v4sf}, - {4, "mxcsr", &builtin_type_int32} + /* 0 */ {8, "rax", &builtin_type_int64}, + /* 1 */ {8, "rbx", &builtin_type_int64}, + /* 2 */ {8, "rcx", &builtin_type_int64}, + /* 3 */ {8, "rdx", &builtin_type_int64}, + /* 4 */ {8, "rsi", &builtin_type_int64}, + /* 5 */ {8, "rdi", &builtin_type_int64}, + /* 6 */ {8, "rbp", &builtin_type_void_func_ptr}, + /* 7 */ {8, "rsp", &builtin_type_void_func_ptr}, + /* 8 */ {8, "r8", &builtin_type_int64}, + /* 9 */ {8, "r9", &builtin_type_int64}, + /* 10 */ {8, "r10", &builtin_type_int64}, + /* 11 */ {8, "r11", &builtin_type_int64}, + /* 12 */ {8, "r12", &builtin_type_int64}, + /* 13 */ {8, "r13", &builtin_type_int64}, + /* 14 */ {8, "r14", &builtin_type_int64}, + /* 15 */ {8, "r15", &builtin_type_int64}, + /* 16 */ {8, "rip", &builtin_type_void_func_ptr}, + /* 17 */ {4, "eflags", &builtin_type_int32}, + /* 18 */ {4, "ds", &builtin_type_int32}, + /* 19 */ {4, "es", &builtin_type_int32}, + /* 20 */ {4, "fs", &builtin_type_int32}, + /* 21 */ {4, "gs", &builtin_type_int32}, + /* 22 */ {10, "st0", &builtin_type_i387_ext}, + /* 23 */ {10, "st1", &builtin_type_i387_ext}, + /* 24 */ {10, "st2", &builtin_type_i387_ext}, + /* 25 */ {10, "st3", &builtin_type_i387_ext}, + /* 26 */ {10, "st4", &builtin_type_i387_ext}, + /* 27 */ {10, "st5", &builtin_type_i387_ext}, + /* 28 */ {10, "st6", &builtin_type_i387_ext}, + /* 29 */ {10, "st7", &builtin_type_i387_ext}, + /* 30 */ {4, "fctrl", &builtin_type_int32}, + /* 31 */ {4, "fstat", &builtin_type_int32}, + /* 32 */ {4, "ftag", &builtin_type_int32}, + /* 33 */ {4, "fiseg", &builtin_type_int32}, + /* 34 */ {4, "fioff", &builtin_type_int32}, + /* 35 */ {4, "foseg", &builtin_type_int32}, + /* 36 */ {4, "fooff", &builtin_type_int32}, + /* 37 */ {4, "fop", &builtin_type_int32}, + /* 38 */ {16, "xmm0", &builtin_type_v4sf}, + /* 39 */ {16, "xmm1", &builtin_type_v4sf}, + /* 40 */ {16, "xmm2", &builtin_type_v4sf}, + /* 41 */ {16, "xmm3", &builtin_type_v4sf}, + /* 42 */ {16, "xmm4", &builtin_type_v4sf}, + /* 43 */ {16, "xmm5", &builtin_type_v4sf}, + /* 44 */ {16, "xmm6", &builtin_type_v4sf}, + /* 45 */ {16, "xmm7", &builtin_type_v4sf}, + /* 46 */ {16, "xmm8", &builtin_type_v4sf}, + /* 47 */ {16, "xmm9", &builtin_type_v4sf}, + /* 48 */ {16, "xmm10", &builtin_type_v4sf}, + /* 49 */ {16, "xmm11", &builtin_type_v4sf}, + /* 50 */ {16, "xmm12", &builtin_type_v4sf}, + /* 51 */ {16, "xmm13", &builtin_type_v4sf}, + /* 52 */ {16, "xmm14", &builtin_type_v4sf}, + /* 53 */ {16, "xmm15", &builtin_type_v4sf}, + /* 54 */ {4, "mxcsr", &builtin_type_int32} }; +/* This array is a mapping from Dwarf-2 register + numbering to GDB's one. Dwarf-2 numbering is + defined in x86-64 ABI, section 3.6. */ +static int x86_64_dwarf2gdb_regno_map[] = { + 0, 1, 2, 3, /* RAX - RDX */ + 4, 5, 6, 7, /* RSI, RDI, RBP, RSP */ + 8, 9, 10, 11, /* R8 - R11 */ + 12, 13, 14, 15, /* R12 - R15 */ + -1, /* RA - not mapped */ + XMM1_REGNUM - 1, XMM1_REGNUM, /* XMM0 ... */ + XMM1_REGNUM + 1, XMM1_REGNUM + 2, + XMM1_REGNUM + 3, XMM1_REGNUM + 4, + XMM1_REGNUM + 5, XMM1_REGNUM + 6, + XMM1_REGNUM + 7, XMM1_REGNUM + 8, + XMM1_REGNUM + 9, XMM1_REGNUM + 10, + XMM1_REGNUM + 11, XMM1_REGNUM + 12, + XMM1_REGNUM + 13, XMM1_REGNUM + 14, /* ... XMM15 */ + ST0_REGNUM + 0, ST0_REGNUM + 1, /* ST0 ... */ + ST0_REGNUM + 2, ST0_REGNUM + 3, + ST0_REGNUM + 4, ST0_REGNUM + 5, + ST0_REGNUM + 6, ST0_REGNUM + 7 /* ... ST7 */ +}; + +static int x86_64_dwarf2gdb_regno_map_length = + sizeof (x86_64_dwarf2gdb_regno_map) / + sizeof (x86_64_dwarf2gdb_regno_map[0]); + /* Number of all registers */ #define X86_64_NUM_REGS (sizeof (x86_64_register_info_table) / \ sizeof (x86_64_register_info_table[0])) @@ -167,7 +196,7 @@ x86_64_register_convert_to_virtual (int regnum, struct type *type, char *from, char *to) { char buf[12]; - DOUBLEST d; + /* We only support floating-point values. */ if (TYPE_CODE (type) != TYPE_CODE_FLT) { @@ -198,6 +227,19 @@ x86_64_register_convert_to_raw (struct type *type, int regnum, memcpy (to, from, FPU_REG_RAW_SIZE); } +/* Dwarf-2 <-> GDB register numbers mapping. */ +int +x86_64_dwarf2_reg_to_regnum (int dw_reg) +{ + if (dw_reg < 0 || dw_reg > x86_64_dwarf2gdb_regno_map_length) + { + warning ("Dwarf-2 uses unmapped register #%d\n", dw_reg); + return dw_reg; + } + + return x86_64_dwarf2gdb_regno_map[dw_reg]; +} + /* This is the variable that is set with "set disassembly-flavour", and its legitimate values. */ static const char att_flavour[] = "att"; @@ -331,18 +373,19 @@ classify_argument (struct type *type, case TYPE_CODE_STRUCT: { int j; - for (j = 0; j < type->nfields; ++j) + for (j = 0; j < TYPE_NFIELDS (type); ++j) { - int num = classify_argument (type->fields[j].type, + int num = classify_argument (TYPE_FIELDS (type)[j].type, subclasses, - (type->fields[j].loc.bitpos - + bit_offset) % 256); + (TYPE_FIELDS (type)[j].loc. + bitpos + bit_offset) % 256); if (!num) return 0; for (i = 0; i < num; i++) { int pos = - (type->fields[j].loc.bitpos + bit_offset) / 8 / 8; + (TYPE_FIELDS (type)[j].loc.bitpos + + bit_offset) / 8 / 8; classes[i + pos] = merge_classes (subclasses[i], classes[i + pos]); } @@ -353,7 +396,7 @@ classify_argument (struct type *type, { int num; - num = classify_argument (type->target_type, + num = classify_argument (TYPE_TARGET_TYPE (type), subclasses, bit_offset); if (!num) return 0; @@ -372,10 +415,10 @@ classify_argument (struct type *type, { int j; { - for (j = 0; j < type->nfields; ++j) + for (j = 0; j < TYPE_NFIELDS (type); ++j) { int num; - num = classify_argument (type->fields[j].type, + num = classify_argument (TYPE_FIELDS (type)[j].type, subclasses, bit_offset); if (!num) return 0; @@ -385,6 +428,8 @@ classify_argument (struct type *type, } } break; + default: + break; } /* Final merger cleanup. */ for (i = 0; i < words; i++) @@ -447,6 +492,8 @@ classify_argument (struct type *type, } case TYPE_CODE_VOID: return 0; + default: /* Avoid warning. */ + break; } internal_error (__FILE__, __LINE__, "classify_argument: unknown argument type"); @@ -609,7 +656,7 @@ x86_64_push_arguments (int nargs, struct value **args, CORE_ADDR sp, static int int_parameter_registers[INT_REGS] = { 5 /* RDI */ , 4 /* RSI */ , 3 /* RDX */ , 2 /* RCX */ , - 8 /* R8 */ , 9 /* R9 */ + 8 /* R8 */ , 9 /* R9 */ }; /* XMM0 - XMM15 */ static int sse_parameter_registers[SSE_REGS] = { @@ -752,13 +799,24 @@ x86_64_store_return_value (struct type *type, char *valbuf) } -static char * +char * x86_64_register_name (int reg_nr) { if (reg_nr < 0 || reg_nr >= X86_64_NUM_REGS) return NULL; return x86_64_register_info_table[reg_nr].name; } + +int +x86_64_register_number (const char *name) +{ + int reg_nr; + + for (reg_nr = 0; reg_nr < X86_64_NUM_REGS; reg_nr++) + if (strcmp (name, x86_64_register_info_table[reg_nr].name) == 0) + return reg_nr; + return -1; +} @@ -800,10 +858,10 @@ x86_64_frameless_function_invocation (struct frame_info *frame) CORE_ADDR x86_64_skip_prologue (CORE_ADDR pc) { - int i, firstline, currline; + int i; struct symtab_and_line v_sal; struct symbol *v_function; - CORE_ADDR salendaddr = 0, endaddr = 0; + CORE_ADDR endaddr; /* We will handle only functions beginning with: 55 pushq %rbp @@ -817,7 +875,7 @@ x86_64_skip_prologue (CORE_ADDR pc) /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */ for (i = 0; i < PROLOG_BUFSIZE; i++) if (prolog_expect[i] != prolog_buf[i]) - return pc; /* ... no, it doesn't. Nothing to skip. */ + return pc; /* ... no, it doesn't. Nothing to skip. */ /* OK, we have found the prologue and want PC of the first non-prologue instruction. */ @@ -831,18 +889,13 @@ x86_64_skip_prologue (CORE_ADDR pc) if (!v_function || !v_function->ginfo.value.block || !v_sal.symtab) return pc; - firstline = v_sal.line; - currline = firstline; - salendaddr = v_sal.end; endaddr = v_function->ginfo.value.block->endaddr; for (i = 0; i < v_sal.symtab->linetable->nitems; i++) - if (v_sal.symtab->linetable->item[i].line > firstline - && v_sal.symtab->linetable->item[i].pc >= salendaddr + if (v_sal.symtab->linetable->item[i].pc >= pc && v_sal.symtab->linetable->item[i].pc < endaddr) { pc = v_sal.symtab->linetable->item[i].pc; - currline = v_sal.symtab->linetable->item[i].line; break; } @@ -859,7 +912,7 @@ x86_64_breakpoint_from_pc (CORE_ADDR * pc, int *lenptr) } static struct gdbarch * -i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) +x86_64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { struct gdbarch *gdbarch; struct gdbarch_tdep *tdep; @@ -885,7 +938,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) break; default: internal_error (__FILE__, __LINE__, - "i386_gdbarch_init: unknown machine type"); + "x86_64_gdbarch_init: unknown machine type"); } break; case bfd_mach_i386_i386: @@ -902,12 +955,12 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) return arches->gdbarch; default: internal_error (__FILE__, __LINE__, - "i386_gdbarch_init: unknown machine type"); + "x86_64_gdbarch_init: unknown machine type"); } break; default: internal_error (__FILE__, __LINE__, - "i386_gdbarch_init: unknown machine type"); + "x86_64_gdbarch_init: unknown machine type"); } } @@ -927,7 +980,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) break; default: internal_error (__FILE__, __LINE__, - "i386_gdbarch_init: unknown machine type"); + "x86_64_gdbarch_init: unknown machine type"); } set_gdbarch_long_bit (gdbarch, 64); @@ -967,7 +1020,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_fp0_regnum (gdbarch, X86_64_NUM_GREGS); /* First FPU floating-point register. */ set_gdbarch_read_fp (gdbarch, cfi_read_fp); - set_gdbarch_write_fp (gdbarch, cfi_write_fp); /* Discard from the stack the innermost frame, restoring all registers. */ set_gdbarch_pop_frame (gdbarch, x86_64_pop_frame); @@ -1056,8 +1108,11 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_inner_than (gdbarch, core_addr_lessthan); - set_gdbarch_breakpoint_from_pc (gdbarch, x86_64_breakpoint_from_pc); + set_gdbarch_breakpoint_from_pc (gdbarch, + (gdbarch_breakpoint_from_pc_ftype *) + x86_64_breakpoint_from_pc); + set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); /* Amount PC must be decremented by after a breakpoint. This is often the number of bytes in BREAKPOINT but not always. */ @@ -1065,13 +1120,15 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Use dwarf2 debug frame informations. */ set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info); + set_gdbarch_dwarf2_reg_to_regnum (gdbarch, x86_64_dwarf2_reg_to_regnum); + return gdbarch; } void _initialize_x86_64_tdep (void) { - register_gdbarch_init (bfd_arch_i386, i386_gdbarch_init); + register_gdbarch_init (bfd_arch_i386, x86_64_gdbarch_init); /* Initialize the table saying where each register starts in the register file. */ diff --git a/contrib/gdb/gdb/x86-64-tdep.h b/contrib/gdb/gdb/x86-64-tdep.h index d15b8e71e7f0..edbfdf36f75f 100644 --- a/contrib/gdb/gdb/x86-64-tdep.h +++ b/contrib/gdb/gdb/x86-64-tdep.h @@ -28,6 +28,10 @@ extern int x86_64_num_regs; extern int x86_64_num_gregs; +int x86_64_register_number (const char *name); +char *x86_64_register_name (int reg_nr); + + gdbarch_frame_saved_pc_ftype x86_64_linux_frame_saved_pc; gdbarch_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call;