summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1996-06-07 11:08:08 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1996-06-07 11:08:08 +0000
commit5e8f84744ab42cf6648e9cc6fa9aa4f6a713a484 (patch)
tree95c644446f498bed99df8b6b2356775209a34a43 /gnu/usr.bin/binutils
parentd671f825bb877aa8089bd042d91e61f7e3160825 (diff)
(Correct) Import of Cygnus binutils snapshot taken 960607
Diffstat (limited to 'gnu/usr.bin/binutils')
-rw-r--r--gnu/usr.bin/binutils/.cvsignore31
-rw-r--r--gnu/usr.bin/binutils/CYGNUS35
-rw-r--r--gnu/usr.bin/binutils/ChangeLog4237
-rw-r--r--gnu/usr.bin/binutils/bfd/coff-aux.c332
-rw-r--r--gnu/usr.bin/binutils/bfd/elf64-mips.c1931
-rw-r--r--gnu/usr.bin/binutils/bfd/freebsd.h109
-rw-r--r--gnu/usr.bin/binutils/bfd/hosts/m68kaux.h16
-rw-r--r--gnu/usr.bin/binutils/bfd/hosts/m68klinux.h6
-rw-r--r--gnu/usr.bin/binutils/bfd/i386freebsd.c33
-rw-r--r--gnu/usr.bin/binutils/bfd/ihex.c1023
-rw-r--r--gnu/usr.bin/binutils/bfd/m68klinux.c767
-rw-r--r--gnu/usr.bin/binutils/bfd/netbsd-core.c309
-rw-r--r--gnu/usr.bin/binutils/bfd/ns32k.h41
-rw-r--r--gnu/usr.bin/binutils/bfd/ppcboot.c535
-rw-r--r--gnu/usr.bin/binutils/bfd/stabs.c529
-rw-r--r--gnu/usr.bin/binutils/binutils/budbg.h58
-rw-r--r--gnu/usr.bin/binutils/binutils/debug.c3501
-rw-r--r--gnu/usr.bin/binutils/binutils/debug.h798
-rw-r--r--gnu/usr.bin/binutils/binutils/dep-in.sed16
-rw-r--r--gnu/usr.bin/binutils/binutils/ieee.c7485
-rw-r--r--gnu/usr.bin/binutils/binutils/prdbg.c1859
-rw-r--r--gnu/usr.bin/binutils/binutils/rdcoff.c874
-rw-r--r--gnu/usr.bin/binutils/binutils/rddbg.c432
-rw-r--r--gnu/usr.bin/binutils/binutils/stabs.c4967
-rw-r--r--gnu/usr.bin/binutils/binutils/wrstabs.c2404
-rw-r--r--gnu/usr.bin/binutils/config/mh-m68kpic1
-rw-r--r--gnu/usr.bin/binutils/config/mh-necv411
-rw-r--r--gnu/usr.bin/binutils/config/mt-m68kpic1
-rw-r--r--gnu/usr.bin/binutils/etc/ChangeLog288
-rw-r--r--gnu/usr.bin/binutils/include/coff/aux-coff.h31
-rw-r--r--gnu/usr.bin/binutils/include/elf/sparc.h71
-rw-r--r--gnu/usr.bin/binutils/libiberty/atexit.c14
-rw-r--r--gnu/usr.bin/binutils/libiberty/choose-temp.c144
-rw-r--r--gnu/usr.bin/binutils/libiberty/xstrdup.c17
-rw-r--r--gnu/usr.bin/binutils/symlink-tree46
35 files changed, 32952 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils/.cvsignore b/gnu/usr.bin/binutils/.cvsignore
new file mode 100644
index 00000000000..944dd6db952
--- /dev/null
+++ b/gnu/usr.bin/binutils/.cvsignore
@@ -0,0 +1,31 @@
+*-all
+*-co
+*-dirs
+*-done
+*-info
+*-install
+*-install-info
+*-src
+*-stamp-*
+*-tagged
+blockit
+cfg-paper.info
+config.status
+configure.aux
+configure.cp
+configure.cps
+configure.dvi
+configure.fn
+configure.fns
+configure.ky
+configure.kys
+configure.log
+configure.pg
+configure.pgs
+configure.toc
+configure.tp
+configure.tps
+configure.vr
+configure.vrs
+dir.info
+Makefile
diff --git a/gnu/usr.bin/binutils/CYGNUS b/gnu/usr.bin/binutils/CYGNUS
new file mode 100644
index 00000000000..13cc014e9ed
--- /dev/null
+++ b/gnu/usr.bin/binutils/CYGNUS
@@ -0,0 +1,35 @@
+About Cygnus Support
+*********************
+
+ Cygnus Support was founded in 1989 to provide commercial support for
+free software. Cygnus supplies products and services that benefit
+advanced development groups by allowing them to use state-of-the-art
+tools without having to maintain them. With Cygnus Support, sites that
+once were forced to do their own tool support can recover that valuable
+staff time. Former users of proprietary software now may choose
+supported free software, combining the advantages of both worlds.
+
+ Free software is faster, more powerful, and more portable than its
+proprietary counterparts. It evolves faster because users who want to
+make improvements are free to do so. Cygnus tracks these improvements
+and integrates them into tested, stable versions ready for commercial
+use, then backs this software with comprehensive support.
+
+ With Cygnus Support as your partner, you will have the software and
+the support you need to meet your business objectives. Cygnus is
+intimately familiar with this software from extensive experience using,
+debugging, and implementing it. You get direct access to the most
+qualified support people: the authors of the software.
+
+ Because all our improvements are also free software, you can
+distribute them widely within your organization, or to your customers,
+without extra cost.
+
+ Cygnus Support
+ 1937 Landings Drive
+ Mountain View, CA 94043
+
+ +1 415 903 1400
+ hotline: +1 415 903 1401
+ email: `info@cygnus.com'
+ fax: +1 415 903 0122
diff --git a/gnu/usr.bin/binutils/ChangeLog b/gnu/usr.bin/binutils/ChangeLog
new file mode 100644
index 00000000000..55a53065d96
--- /dev/null
+++ b/gnu/usr.bin/binutils/ChangeLog
@@ -0,0 +1,4237 @@
+Thu Jun 6 16:27:05 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (powerpcle-*-solaris*): Until we get shared
+ libraries working, don't build gdb, sim, make, tcl, tk, or
+ expect.
+
+Tue Jun 4 20:41:45 1996 Per Bothner <bothner@deneb.cygnus.com>
+
+ * config.guess: Merge with FSF:
+
+ Mon Jun 3 08:49:14 1996 Karl Heuer <kwzh@gnu.ai.mit.edu>
+ * config.guess (*:Linux:*:*): Add guess for sparc-unknown-linux.
+
+ Fri May 24 18:34:53 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+ * config.guess (AViiON:dgux:*:*): Fix typo in recognizing mc88110.
+
+ Fri Apr 12 20:03:59 1996 Per Bothner <bothner@spiff.gnu.ai.mit.edu>
+ * config.guess: Combine two OSF1 rules.
+ Also recognize field test versions. From mjr@zk3.dec.com.
+ * config.guess (dgux): Use /usr/bin/uname rather than uname,
+ because GNU uname does not support -p. From pmr@pajato.com.
+
+Tue Jun 4 11:07:25 1996 Tom Tromey <tromey@csk3.cygnus.com>
+
+ * Makefile.in (MAKEDIRS): Removed $(tooldir).
+
+Tue May 28 12:30:50 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-README: Document GCCIncludes.
+
+Sun May 26 15:16:27 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in (alpha-*-linux*): Set enable_shared to yes.
+
+Tue May 21 15:41:39 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-configure: Handle --enable-FOO and --disable-FOO.
+
+Mon May 20 10:12:29 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * configure.in (*-*-cygwin32): Configure make.
+
+Tue May 7 14:19:42 1996 Tom Tromey <tromey@snuffle.cygnus.com>
+
+ * Makefile.in (inet-install): Quote value of INSTALL_MODULES.
+
+Fri May 3 08:57:17 1996 Tom Tromey <tromey@lisa.cygnus.com>
+
+ * Makefile.in (all-inet): Depend on all-perl.
+
+ * Makefile.in (inet-install): New target.
+
+ * Makefile.in (all-inet): Depend on all-tcl.
+ (all-inet): Depend on all-send-pr.
+
+Tue Apr 30 13:55:51 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (powerpcle-*-solaris*): Turn off tk and tcl
+ temporarily.
+
+Thu Apr 25 11:48:20 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Don't configure --with-gnu-ld on AIX.
+
+Thu Apr 25 06:33:36 1996 Michael Meissner <meissner@wogglebug.tiac.net>
+
+ * configure.in (powerpcle-*-solaris*): Turn off gdb temporarily.
+
+Tue Apr 23 09:07:39 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * Makefile.in (ALL_MODULES): Added all-inet.
+ (CROSS_CHECK_MODULES): Added check-inet.
+ (INSTALL_MODULES): Added install-inet.
+ (CLEAN_MODULES): Added clean-inet.
+ (all-indent): New target.
+
+ * configure.in (host_tools): Added inet.
+ (native_only): Added inet.
+ (noconfigdirs): Added inet.
+
+Fri Apr 19 15:35:29 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Don't configure libgloss if we are not configuring
+ newlib.
+
+Wed Apr 17 19:30:01 1996 Rob Savoye <rob@chinadoll.cygnus.com>
+
+ * configure.in: Don't configure libgloss for unsupported
+ architectures.
+
+Tue Apr 16 11:17:05 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (CLEAN_MODULES): Add clean-apache.
+
+Mon Apr 15 15:09:05 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * Makefile.in (ALL_MODULES): Include all-apache.
+ (CROSS_CHECK_MODULES): Include check-apache.
+ (INSTALL_MODULES): Include install-apache.
+ (all-apache): New target.
+
+ * configure.in: Added apache everywhere perl is seen.
+
+Mon Apr 15 14:59:13 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in: Add support for clean-{module} and
+ clean-target-{module} rules.
+
+Wed Apr 10 21:37:41 PDT 1996 Marilyn E. Sander <msander@cygnus.com>
+
+ * configure.in (*-*-ose) do not build libgloss.
+
+Mon Apr 8 16:16:20 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config.guess (prep*:SunOS:5.*:*): Turn into
+ powerpele-unknown-solaris2.
+
+Mon Apr 8 14:45:41 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Permit --enable-shared to specify a list of
+ directories.
+
+Fri Apr 5 08:17:57 1996 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in (host==solaris): Pass only the first word of $CC
+ to /usr/bin/which when checking if we're using /usr/ccs/bin/cc.
+
+Fri Apr 5 03:16:13 1996 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Makefile.in (BASE_FLAGS_TO_PASS): pass down $(MAKE).
+
+Thu Mar 28 14:11:11 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * Makefile.in (ALL_MODULES): Include all-perl.
+ (CROSS_CHECK_MODULES): Include check-perl.
+ (INSTALL_MODULES): Include install-perl.
+ (ALL_X11_MODULES): Include all-guile.
+ (CHECK_X11_MODULES): Include check-guile.
+ (INSTALL_X11_MODULES): Include install-guile.
+ (all-perl): New target.
+ (all-guile): New target.
+
+ * configure.in (host_tools): Include perl and guile.
+ (native_only): Include perl and guile.
+ (noconfigdirs): Don't build guile and perl; no ports have been
+ done.
+
+Tue Mar 26 21:18:50 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * configure (--enable-*): Handle quoted option lists such as
+ --enable-sim-cflags='-g0 -O' better.
+
+Thu Mar 21 11:53:08 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in ({,inst}all-target): New rule so we can make and
+ install all of the target directories easily.
+
+Wed Mar 20 18:10:57 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * configure.in: Add missing global flag in sed substitution when
+ deleting `target-' from ${configdirs}.
+
+Thu Mar 14 19:15:06 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (DO_X): Don't get confused if CC contains `=' in an
+ option.
+
+ * configure.in (mips*-nec-sysvr4*): Use a host_makefile_frag of
+ config/mh-necv4.
+
+ * install.sh: Correct misspelling of transformbasename.
+
+ * config.guess: Recognize mips-*-sysv*.
+
+Mon Mar 11 15:36:42 1996 Dawn Perchik <dawn@critters.cygnus.com>
+
+ * config.sub: Recognize mon960.
+
+Sun Mar 10 13:18:38 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Restore Canadian Cross handling of BISON and LEX,
+ removed in Feb 20 change.
+
+Fri Mar 8 20:07:09 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * README: Suggestions from Torbjorn Granlund <tege@matematik.su.se>:
+ Mention make install. Remove the old copyright date as well the
+ clumsy and rather pointless copyright on the README file.
+
+Fri Mar 8 17:51:35 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in ($(CONFIGURE_TARGET_MODULES)): If there is a
+ Makefile after running symlink-tree, then run `make distclean' to
+ avoid clobbering any generated files in srcdir.
+
+Tue Mar 5 08:21:44 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in (m68k-*-netbsd*): Build everything now.
+
+Wed Feb 28 12:25:46 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * Makefile.in (taz): Fix quoting.
+
+Tue Feb 27 11:33:57 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * configure.in (sparclet-*-*): Build everything now.
+
+Tue Feb 27 14:31:51 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * configure.in (m68k-*-linux*): New host.
+
+Mon Feb 26 14:32:44 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Check for bison before byacc.
+
+Tue Feb 20 23:12:35 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in configure: Change the way LEX and BISON/YACC are
+ set. configure now defines DEFAULT_LEX and DEFAULT_YACC by
+ searching PATH. These are used as fallbacks by Makefile.in if
+ flex/bison/byacc aren't in objdir.
+
+Mon Feb 19 11:45:30 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in: Make everything which depends upon all-bfd also
+ depend upon all-opcodes, in case --with-commonbfdlib is used.
+
+Thu Feb 15 19:50:50 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (host *-*-cygwin32): Don't build gdb if we are
+ building NT native compilers on Unix.
+
+Thu Feb 15 17:42:25 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Don't get CC from the host Makefile fragment if we
+ can find gcc in PATH, or if this is a Canadian Cross. Move the
+ Solaris test for /usr/ucb/cc to the post target script, just after
+ the compiler sanity test.
+
+Wed Feb 14 16:57:40 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config.sub: Merge with FSF.
+
+Tue Feb 13 14:27:48 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (RPATH_ENVVAR): New variable.
+ (REALLY_SET_LIB_PATH): Use it.
+ * configure.in: On HP/UX, set RPATH_ENVVAR to SHLIB_PATH.
+
+Mon Feb 12 15:28:49 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * config.sub, configure.in: Recognize sparclet cpu.
+
+Mon Feb 12 15:33:59 1996 Christian Bauernfeind <chrisbfd@theorie3.physik.uni-erlangen.de>
+
+ * config.guess: Support m68k-cbm-sysv4.
+
+Sat Feb 10 12:06:42 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config.guess (*:Linux:*:*): Guess m68k-unknown-linux and
+ m68k-unknown-linuxaout from linker help string. Put quotes around
+ $ld_help_string.
+
+Thu Dec 7 09:03:24 1995 Tom Horsley <Tom.Horsley@mail.hcsc.com>
+
+ * config.guess (powerpc-harris-powerunix): Add guess for port
+ to new target.
+
+Thu Feb 8 15:37:52 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * config.guess (UNAME_VERSION): Recognize X4.x as an OSF version.
+
+Mon Feb 5 16:36:51 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: If --enable-shared was used, set SET_LIB_PATH to
+ $(REALLY_SET_LIB_PATH) in Makefile.
+ * Makefile.in (SET_LIB_PATH): New variable.
+ (REALLY_SET_LIB_PATH): New variable.
+ ($(DO_X)): Use $(SET_LIB_PATH).
+ (install.all, gcc-no-fixedincludes, $(ALL_MODULES)): Likewise.
+ ($(NATIVE_CHECK_MODULES), $(CROSS_CHECK_MODULES)): Likewise.
+ ($(INSTALL_MODULES), $(CONFIGURE_TARGET_MODULES)): Likewise.
+ ($(ALL_TARGET_MODULES), $(CHECK_TARGET_MODULES)): Likewise.
+ ($(INSTALL_TARGET_MODULES), $(ALL_X11_MODULES)): Likewise.
+ ($(CHECK_X11_MODULES), $(INSTALL_X11_MODULES)): Likewise.
+ (all-gcc, all-bootstrap, check-gcc, install-gcc): Likewise.
+ (install-dosrel): Likewise.
+ (all-opcodes): Depend upon all-libiberty.
+
+Sun Feb 4 16:51:11 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * config.guess (*:CYGWIN*): New
+
+Sat Feb 3 10:42:35 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (all-target-winsup): All all-target-libiberty.
+
+Fri Feb 2 17:58:56 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (noconfigdirs): Add missing # in front of comment.
+
+Thu Feb 1 14:38:13 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * configure.in: add second pass to things added to noconfigdirs
+ so *-gm-magic can exclude libgloss properly.
+
+Thu Feb 1 11:10:16 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-configure (extralibs_name, rez_name): Set correctly
+ for MWC68K compiler.
+
+ * mpw-README: Add more info on the necessary build tools.
+
+Thu Feb 1 10:22:38 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * configure.in, config.sub: Recognize cygwin32.
+
+Wed Jan 31 14:17:10 1996 Richard Henderson <rth@tamu.edu>
+
+ * config.guess, config.sub: Recognize A/UX.
+
+Wed Jan 31 13:52:14 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config.sub: Merge with gcc/config.sub.
+
+Thu Jan 25 11:01:10 1996 Raymond Jou <rjou@mexican.cygnus.com>
+
+ * mpw-build.in (do-binutils): Add build of stamps.
+
+Thu Jan 25 17:05:26 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config.sub: Add recognition for mips64vr4100*-* targets.
+
+Wed Jan 24 12:47:55 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * test-build.mk: Add checking of `hpux9' rather than just `hpux'.
+ Add creation of gconfigargs with `--enable-shared' turned on.
+ ($(host)-stamp-stage2-configured): Pass $(gconfigargs).
+ ($(host)-stamp-stage3-configured): Likewise.
+ (HOLES): Add chatr and ldd.
+ (i386-ncr-sysv4.3*): Add use of /usr/ccs/bin in the PATH and HOLE_DIRS.
+
+Wed Jan 24 20:32:30 1996 Torbjorn Granlund <tege@noisy.matematik.su.se>
+
+ * configure: Pass --nfp to recursive configures.
+
+Mon Jan 22 10:41:56 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * Makefile.in (DLLTOOL): New.
+ (DLLTOOL_FOR_TARGET): New.
+ (EXTRA_HOST_FLAGS): Pass down DLLTOOL.
+ (EXTRA_TARGET_FLAGS): Ditto.
+ (EXTRA_GCC_FLAGS): Ditto.
+ (CONFIGURE_TARGET_MODULES): Ditto.
+ (DO_X): Ditto.
+ * configure: Add DLLTOOL.
+
+Fri Jan 19 13:30:15 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ SCO OpenServer 5 changes from Robert Lipe <robertl@dgii.com>:
+ * configure.in (i[345]86-*-sco3.2v5*): Use mh-sysv instead of
+ mh-sco, since old workarounds no longer needed, and don't
+ build ld, since libraries have weak symbols in COFF.
+
+Sun Jan 14 23:01:31 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (CONFIGURE_TARGET_MODULES): Add missing ';'.
+
+Fri Jan 12 15:25:35 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Make sure that ${CC} can be used to compile an
+ executable.
+
+Sat Jan 6 07:23:33 1996 Michael Meissner <meissner@wogglebug.tiac.net>
+
+ * Makefile.in (all-gdb): Depend on $(GDB_TK).
+ * configure (GDB_TK): Set GDB_TK to either "all-tcl all-tk" or
+ nothing depending on whether gdbtk is being built.
+
+Wed Jan 3 17:54:41 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in (newlib.tar.gz): Delete building of newlib's info files.
+
+Mon Jan 1 19:09:14 1996 Brendan Kehoe <brendan@rtl.cygnus.com>
+
+ * configure.in (noconfigdirs): Put ld or gas in this early, if the
+ user specifically used --with-gnu-ld=no or --with-gnu-as=no.
+
+Sat Dec 30 16:08:57 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config-ml.in: Add support for
+ --disable-{softfloat,m68881,m68000,m68020} on m68*-*-*.
+ Simplify setting of multidirs from --disable-foo.
+
+Fri Dec 29 07:56:11 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (EXTRA_GCC_FLAGS): If any of the make variables
+ LANGUAGES, BOOT_CFLAGS, STMP_FIXPROTO, LIMITS_H_TEST,
+ LIBGCC1_TEST, LIBGCC2_CFLAGS, LIBGCC2_INCLUDES, and ENQUIRE are
+ non-empty, pass them on to the GCC make.
+ (all-bootstrap): New rule that is like all-gcc, except it executes
+ the GCC bootstrap rule instead of the GCC all rule.
+
+Wed Dec 27 15:51:48 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config-ml.in (ml_realsrcdir): New, to account for ${subdir}.
+
+Tue Dec 26 11:45:31 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config.guess (AViiON:dgux:*:*): Update from FSF to add pentium
+ DG/UX support.
+
+Fri Dec 15 10:01:27 1995 Stan Cox <coxs@dg-rtp.dg.com>
+
+ * config.sub (i*86*) Change [345] to [3456]
+
+Wed Dec 20 17:41:40 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * configure.in (noconfigdirs): Add gas or ld if --with-gnu-as=no or
+ --with-gnu-ld=no.
+
+Wed Dec 20 15:15:35 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config-ml.in (rs6000*, powerpc*): Add switches to control which
+ AIX multilibs get built.
+
+Mon Dec 18 17:55:46 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in (i386-win32): Don't build expect if we're not
+ building the tcl subdir.
+
+Mon Dec 18 11:47:19 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in: (configure-target-examples, all-target-examples):
+ New targets, configure and build example programs.
+
+Fri Dec 15 16:13:03 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-configure: If an mpw-config.in generated a file mk.sed,
+ use it as input to sedit the generated MPW makefile.
+ * mpw-README: Add a suggestion about Gestalt.h.
+
+Wed Dec 13 16:43:51 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config.sub: Accept *-*-ieee*.
+
+Tue Dec 12 11:52:57 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (local-distclean): Remove $(TARGET_SUBDIR). From
+ Ronald F. Guilmette <rfg@monkeys.com>.
+
+Mon Dec 11 15:31:58 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in (host==powerpc-pe): Add many directories to noconfigdirs
+ for powerpc-pe native.
+ (target==i386-win32): add tcl, make to noconfigdirs if canadian cross.
+ (target==powerpc-pe): duplicate i386-win32 entry.
+
+Sat Dec 9 14:58:28 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * configure.in (noconfigdirs): Exclude target-newlib for all versions
+ of vxworks, not just vxworks5.1.
+
+Mon Dec 4 12:05:40 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-configure: Add support for exec-prefix.
+
+Mon Dec 4 10:22:50 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config.guess: Recognize HP model 816 machines as having
+ a PA1.1 processor.
+
+Mon Dec 4 12:38:15 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Ignore new autoconf configure options.
+
+Thu Nov 30 14:45:25 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/mt-v810 (CC_FOR_TARGET): Add -ansi flag. NEC compiler
+ defaults to K&R mode, but doesn't have varargs.h, so we have to
+ compile in ANSI mode.
+
+Thu Nov 30 16:57:33 1995 Per Bothner <bothner@wombat.gnu.ai.mit.edu>
+
+ * config.guess: Recognize Pentium under SCO.
+ From Robert Lipe <robertl@arnet.com>.
+
+Wed Nov 29 13:49:08 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in (noconfigdirs): Disable target-libio on v810-*-*.
+ * config/mt-v810 (CC_FOR_TARGET, AS_FOR_TARGET, AR_FOR_TARGET,
+ RANLIB_FOR_TARGET): Set as appropriate for NEC v810 toolchain.
+
+Wed Nov 29 12:12:01 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Don't configure gas for alpha-dec-osf*.
+
+Tue Nov 28 17:16:48 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Default to --with-stabs for some targets for which
+ it makes sense: mips*-*-*, alpha*-*-osf*, i[345]86*-*-sysv4* and
+ i[345]86*-*-unixware*.
+
+Mon Nov 27 13:44:15 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config-ml.in: Get list of multidirs using gcc --print-multi-lib
+ rather than basing it on the target. Simplify handling of options
+ controlling which directories to configure. Remove extraneous
+ slash in multi-clean target.
+
+Fri Nov 24 17:29:29 1995 Doug Evans <dje@deneb.cygnus.com>
+
+ * config-ml.in: Prefix more variables with ml_ so they don't collide
+ with configure's.
+
+Wed Nov 22 11:27:02 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Don't turn -v into --v.
+
+Tue Nov 21 16:48:02 1995 Doug Evans <dje@deneb.cygnus.com>
+
+ * configure.in (targargs): Fix typo.
+
+ * Makefile.in (DEVO_SUPPORT): Add symlink-tree.
+
+Tue Nov 21 14:08:28 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Strip --host and --target options from
+ CONFIG_ARGUMENTS, and always configure for --host only. Add
+ --with-cross-host option when building with a cross-compiler.
+ * configure: Canonicalize the arguments put into config.status by
+ always using `=' for an option with an argument. Pass a presumed
+ --host or --target explicitly.
+
+Fri Nov 17 17:50:30 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config.sub: Merge -macos*, -magic*, -pe*, and -win32 cases
+ into general OS recognition case.
+
+Fri Nov 17 17:42:25 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in (target_configdirs): add target-winsup only
+ for win32 target systems.
+
+Thu Nov 16 14:04:47 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (all-target-libgloss): Depend upon
+ configure-target-newlib, since when libgloss is built it looks to
+ see if the newlib directory exists.
+
+Wed Nov 15 14:47:52 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * Makefile.in (DEVO_SUPPORT): Use config-ml.in instead of
+ cfg-ml-*.in.
+
+Wed Nov 15 11:45:23 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Handle LD and LD_FOR_TARGET when configuring a
+ Canadian Cross.
+
+Tue Nov 14 15:03:12 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * config/mh-i386win32: add LD_FOR_TARGET.
+
+Tue Nov 14 14:56:11 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in (target_libs): add target-winsup.
+ (target==i386-win32): add patch diff flex make to $noconfigdirs.
+ (target==ppcle-pe): remove ld from $noconfigdirs.
+
+Tue Nov 14 01:25:50 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in (CONFIGURE_TARGET_MODULES): Pass --with-target-subdir.
+ Preserve relative path names in $srcdir. Build symlink tree if
+ configuring cross target dir and srcdir=. (= no VPATH support).
+ (configure-target-libg++): Depend on configure-target-librx.
+ * cfg-ml-com.in, cfg-ml-pos.in: Deleted.
+ * config-ml.in: New file.
+ * symlink-tree: New file.
+ * configure: Ensure srcdir="." if that's what it is.
+
+Mon Nov 13 12:34:20 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-README: Clarify some phrasing, add notes about CodeWarrior
+ includes and FLEX_SKELETON setting.
+ * mpw-configure (--with-gnu-ld): New option, controls whether
+ to use PPCLink or ld with PowerMac GCC.
+ * mpw-build.in (all-grez, do-grez, install-grez): New targets.
+ * mpw-config.in: Configure grez if targeting Mac.
+
+ * config.sub: Accept pmac and pmac-mpw as names for PowerMacs,
+ accept mpw and mac-mpw as names for m68k Macs, change macos7 to
+ just macos.
+ * configure.in: Configure grez resource compiler if targeting Mac.
+ * Makefile.in (all-grez, install-grez): New targets.
+
+Wed Nov 8 17:33:51 1995 Jason Merrill <jason@yorick.cygnus.com>
+
+ * configure: CXX defaults to gcc, not g++. If we find
+ gcc in the path, set CC to gcc -O2.
+
+Tue Nov 7 15:45:17 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Default ${build} correctly. Avoid picking up extra
+ spaces when reading CC and CXX from Makefile. When doing a
+ Canadian Cross, use plausible default values for numerous
+ variables.
+ * configure.in: When doing a Canadian Cross, don't try to
+ configure tools whose configure script can't handle it.
+
+Mon Nov 6 19:32:17 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * cfg-ml-com.in (sh-*-*): Add m2 and ml/m2 to multidirs.
+
+Sun Nov 5 00:15:41 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * configure: Remove dubious bug reporting address.
+
+Fri Nov 3 08:17:54 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in ($(CONFIGURE_TARGET_MODULES)): If subdir has
+ configure script, run that instead of this directory's configure.
+ In either case, print a message that we're configuring the sub-dir.
+
+Thu Nov 2 23:23:36 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * configure.in: Before checking for the existence of various files,
+ use sed to filter out "target-".
+
+Thu Nov 2 13:24:56 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (DO_X): Split rule to decrease command line length
+ for systems with small ARG_MAX values. From phdm@info.ucl.ac.be
+ (Philippe De Muyter).
+
+Wed Nov 1 15:18:35 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Makefile.in (all-patch): depend on all-libiberty.
+
+Wed Nov 1 12:23:20 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: If the only directory in target_configdirs which
+ actually exists is libiberty, then set target_configdirs to empty,
+ to avoid trying to build a target libiberty in a gas or gdb
+ distribution.
+
+Tue Oct 31 17:52:39 1995 J.T. Conklin <jtc@slave.cygnus.com>
+
+ * configure.in (host_makefile_frag): Use m68k-sun-sunos* instead
+ of m68k-sun-* when selecting mh-sun3 to avoid matching NetBSD/sun3
+ systems.
+
+Tue Oct 31 16:57:32 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * configure.in (copy_dirs): Use sys-include instead of include
+ for --with-headers option.
+
+Tue Oct 31 10:29:36 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * Makefile.in, configure.in: Make winsup builds work with
+ new scheme.
+
+Mon Oct 30 18:57:09 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Build the linker on AIX.
+
+Mon Oct 30 12:27:16 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in (CC_FOR_TARGET, CXX_FOR_TARGET): Add $(TARGET_SUBDIR)
+ where needed.
+
+Mon Oct 30 12:45:25 1995 Doug Evans <dje@cygnus.com>
+
+ * Makefile.in (all-gcc): Fix typo.
+
+Sat Oct 28 10:27:59 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in ($(CHECK_TARGET_MODULES)): Fix typo.
+
+Fri Oct 27 23:14:12 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * configure.in: Rename libFOO to target-libFOO, and xiberty
+ to target-xiberty, to provide more flexibility.
+ (target_subdir): Define. Create if cross.
+ Set TARGET_SUBDIR in Makefile to ${target_subdir}.
+ * Makefile.in: Rename all-libFOO -> all-target-libFOO, all-xiberty
+ -> all-target-libiberty, configure-libFOO -> configure-target-libFOO,
+ check-libFOO -> check-target-libFOO, etc.
+ ($(DO_X)): Iterate over TARGET_CONFIGDIRS after SUBDIRS.
+ ($(CONFIGURE_TARGET_MODULES), $(CHECK_TARGET_MODULES),
+ $(ALL_TARGET_MODULES), $(INSTALL_TARGET_MODULES)): Update accordingly.
+ (configure-target-XXX): Depend on $(ALL_GCC), not all-gcc, to
+ allow ALL_GCC="" to only configure.
+ (DEVO_SUPPORT): Add cfg-ml-com.in and cfg-ml-pos.in.
+ (ETC_SUPPORT, ETC_SUPPORT_PFX): Merge; update 'taz' accordingly.
+ (LIBGXX_SUPPORT_DIRS): Remove xiberty.
+
+Sat Oct 28 01:53:49 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * Makefile.in (taz): Build "info" in etc explicitly.
+
+Fri Oct 27 09:32:30 1995 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Make sure that CC is undefined (as opposed to
+ null) if toplevel/config/mh-{host} doesn't define it. Fixes a
+ problem with autoconf trying to configure on a host without GCC.
+
+Thu Oct 26 22:35:01 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-configure: Set host alias from choice of host compiler,
+ only use generic MPW Makefile sed if present, edit a file
+ named "hacked_Makefile.in" instead of "Makefile.in" if present.
+ * mpw-README: Add problem notes about CW6 and CW7.
+
+Thu Oct 26 05:45:10 1995 Ken Raeburn <raeburn@kr-pc.cygnus.com>
+
+ * Makefile.in (taz): Use ";" instead of ";;".
+
+Wed Oct 25 15:18:24 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in (taz): Grep for '^diststuff:' or '^info:' in
+ sub-directory Makefiles, instead of using DISTSTUFFDIRS and
+ DISTDOCDIRS.
+ (DISTSTUFFDIRS, DISTDOCDIRS): Removed - no longer used.
+ (newlib.tar.gz): Don't pass DISTDOCDIRS to recursive make.
+
+Wed Oct 25 14:43:55 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in (DISTDOCDIRS): Remove ld gprof bnutils gas libg++ gdb
+ and gnats, because they are now subsumed by DISTSTUFFDIRS.
+ Move bfd to DISTSTUFFDIRS.
+
+Tue Oct 24 18:19:09 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Makefile.in (X11_LIB): Removed.
+ (X11_FLAGS_TO_PASS): pass only X11_EXTRA_CFLAGS and X11_EXTRA_LIBS.
+
+ * configure.in (host_makefile_frag): mh-aix & mh-sun removed.
+
+Sun Oct 22 13:04:42 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * cfg-ml-com.in (powerpc*): Shorten some of the multilib directory
+ names.
+
+Fri Oct 20 18:02:10 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * cfg-ml-com.in (powerpc*-eabi*): Add mcall-aixdesc varients.
+
+Thu Oct 19 10:40:57 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * configure.in (i[345]86-*-win32): Always build newlib.
+ Don't configure cvs, autoconf or texinfo.
+ * Makefile.in (LD_FOR_TARGET): New.
+ (BASE_FLAGS_TO_PASS, EXTRA_TARGET_FLAGS, CONFIGURE_TARGET_MODULES):
+ Pass down LD_FOR_TARGET.
+
+Wed Oct 18 15:53:56 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * winsup: New directory.
+ * Makefile.in: Build winsup.
+ * configure.in: Winsup is configured when target is win32.
+ Can only build win32 target GDB when native.
+
+Mon Oct 16 09:42:31 1995 Jeffrey A Law (law@cygnus.com)
+
+ * config.guess: Recognize HP model 819 machines as having
+ a PA 1.1 processor.
+
+Mon Oct 16 10:49:43 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Fix sed loop which substitutes for CC and CXX to
+ avoid bug found in various sed implementations.
+
+Wed Oct 11 16:16:20 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * cfg-ml-com.in (powerpc-*-eabisim): Delete separate rule for
+ simulator. Use standard powerpc-*-eabi*.
+
+Mon Oct 9 17:21:56 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Stop putting gas and binutils in noconfigdirs for
+ powerpc-*-aix* and rs6000-*-*.
+
+Mon Oct 9 12:38:40 1995 Michael Meissner <meissner@cygnus.com>
+
+ * cfg-ml-com.in (powerpc*-*-eabisim*): Add support for building
+ -mcall-aixdesc libraries.
+
+Fri Oct 6 16:17:57 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ Mon Sep 25 22:49:32 1995 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config.sub (arm | armel | armeb): Fix shell syntax.
+
+Fri Oct 6 14:40:28 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * cfg-ml-com.in ({powerpc,rs6000}-ibm-aix*): Add multilibs for
+ -msoft-float and -mcpu=common support.
+ (powerpc*-*-eabisim*): Add support for building -mcall-aix
+ libraries.
+
+Thu Oct 5 13:26:37 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * configure.in: Allow configuration and build of emacs19 for the alpha.
+
+Wed Oct 4 22:05:36 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in (CC): Get ^CC, not just any old CC, from
+ ${host_makefile_frag}.
+
+Wed Oct 4 21:55:00 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in (CC): Try to get CC from
+ ${srcdir}/${host_makefile_frag}, not ${host_makefile_frag}.
+
+Wed Oct 4 21:44:12 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Makefile.in (TARGET_CONFIGDIRS): configure targetdirs
+ only if it exists in $(srcdir).
+
+Wed Oct 4 11:52:31 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: If CC and CXX are not set in the environment, set
+ them, based on either an existing Makefile or on searching for gcc
+ in PATH. Substitute for CC and CXX in Makefile.
+ * configure.in: Remove libm from target_libs. Separate
+ target_configdirs from configdirs. If CC is not set in
+ environment, try to get it from a host Makefile fragment. Rewrite
+ changes of configdirs to use skipdirs instead. A few minor
+ tweaks. Take directories out of target_configdirs as they are
+ taken out of configdirs. Remove existing Makefile files from
+ subdirectories. Substitute for TARGET_CONFIGDIRS and
+ CONFIG_ARGUMENTS in Makefile.
+ * Makefile.in (TARGET_CONFIGDIRS): New variable, automatically set
+ by configure.in.
+ (CONFIG_ARGUMENTS): Likewise.
+ (CONFIGURE_TARGET_MODULES): New variable.
+ ($(DO_X)): Loop over TARGET_CONFIGDIRS as well as SUBDIRS.
+ ($(CONFIGURE_TARGET_MODULES)): New target.
+ (configure-libg++, configure-libio): New targets.
+ (all-libg++): Depend upon configure-libg++.
+ (all-libio): Depend upon configure-libio.
+ (configure-libgloss, all-libgloss): New targets.
+ (configure-libstdc++): New target.
+ (all-libstdc++): Depend upon configure-libstdc++.
+ (configure-librx, all-librx): New targets.
+ (configure-newlib): New target.
+ (all-newlib): Depend upon configure-newlib
+ (configure-xiberty): New target.
+ (all-xiberty): Depend upon configure-xiberty.
+
+Sat Sep 30 04:32:59 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in (host i[345]86-*-win32): Expand the
+ noconfigdirs again.
+
+Thu Sep 28 21:18:49 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-configure: Fix sed command file name.
+
+Thu Sep 28 17:39:56 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * configure.in (host i[345]86-*-win32): Reduce the
+ noconfigdirs again.
+
+Wed Sep 27 12:24:00 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Don't configure ld and gdb for powerpc*-*-winnt*
+ or powerpc*-*-pe*, since they are not yet supported.
+
+Tue Sep 26 14:30:01 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ Add PowerMac support and many other enhancements.
+ * mpw-configure: New option --cc to select compiler to use,
+ paste options set according to --cc into the generated
+ Makefile, generate the Makefile by sed'ing the Unix Makefile.in
+ if mpw-make.sed is present.
+ * mpw-config.in: Don't test for gC1, test for mpw-touch,
+ add forward includes for PowerPC include files.
+ * mpw-build.in: Build using Makefile.PPC if present.
+ (do-byacc, etc): Remove separate version resource builds.
+ (do-gas): Build "stamps" before "all".
+ (do-gcc): Build "stamps-h" and "stamps-c" before "all".
+ * mpw-README: Update to reflect --cc option, PowerMac support,
+ and recently-reported compatibility problems.
+
+Fri Sep 22 12:15:42 1995 Doug Evans <dje@deneb.cygnus.com>
+
+ * cfg-ml-com.in (m68*-*-*): Only build multilibs for
+ embedded m68k systems (-aout, -coff, -elf, -vxworks).
+ (--with-multilib-top): Pass to recursive invocations.
+
+Tue Sep 19 13:51:05 1995 J.T. Conklin <jtc@blues.cygnus.com>
+
+ * configure.in (noconfigdirs): Disable libg++ and libstdc++ on
+ v810-*-*.
+
+Mon Sep 18 23:08:26 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in (noconfigdirs): Disable bfd, binutils, gas, gcc,
+ gdb, ld and opcodes on v810-*-*.
+
+Sat Sep 16 18:31:08 PDT 1995 Angela Marie Thomas <angela@cygnus.com>
+
+ * config/mh-ncrsvr43: Removed AR_FLAGS
+
+Tue Sep 12 18:03:31 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (DO_X): Change do-realclean to do-maintainer-clean.
+ (local-maintainer-clean): New target.
+ (maintainer-clean): New target.
+ (realclean): Just depend upon maintainer-clean.
+
+Fri Sep 8 17:11:14 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in (noconfigdirs): Disable gdb on m68k-*-netbsd*.
+
+Fri Sep 8 16:46:29 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Build ld in mips*-*-bsd* case.
+
+Thu Sep 7 20:03:41 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * config.sub: Accept -lites* OS. From Ian Dall.
+
+Fri Sep 1 08:06:58 1995 James G. Smith <jsmith@beauty.cygnus.com>
+
+ * config.sub: recognise mips64vr4300 and mips64vr4300el as valid
+ targets.
+
+Wed Aug 30 21:06:50 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in: treat i386-win32 canadian cross the same as
+ i386-go32 canadian cross.
+
+Thu Aug 24 14:53:20 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * cfg-ml-com.in (powerpc*-*-eabisim): Add support for PowerPC
+ running under the simulator to build a reduced set of libraries.
+ (powerpc-*-eabiaix): Add fine grained multilib support added to
+ other powerpc targets yesterday.
+
+Wed Aug 23 09:41:56 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * cfg-ml-com.in (powerpc*): Add support for -disable-biendian,
+ -disable-softfloat, -disable-relocatable, -disable-aix, and
+ -disable-sysv to control which multilib libraries get built.
+
+Thu Aug 17 16:03:41 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ * configure: Add Makefile.tem to list of files to remove in trap
+ handler.
+
+Mon Aug 14 19:27:56 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * config.guess (*Linux*): Add missing "exit"s.
+ Also, need specific check for alpha-unknown-linux (uses COFF).
+
+Fri Aug 11 15:38:20 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * config.guess: Merge with FSF:
+
+ Wed Jun 28 17:57:27 1995 David Edelsohn <edelsohn@mhpcc.edu>
+ * config.guess (AIX4): More robust release numbering discovery.
+
+ Thu Jun 22 19:01:24 1995 Kenneth Stailey (kstailey@eagle.dol-esa.gov)
+ * config.guess (i386-sequent-ptx): Properly get version number.
+
+ Thu Jun 22 18:36:42 1995 Uwe Seimet (seimet@iris1.chemie.uni-kl.de)
+ * config.guess (mips:*:4*:UMIPS): New case.
+
+Mon Aug 7 09:21:35 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * configure.in (i386-go32 host): Fix typo (deja-gnu -> dejagnu).
+ (i386-win32 host): Likewise. Don't build readline.
+
+Sat Aug 5 09:51:49 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * Makefile.in (GDBTK_SUPPORT_DIRS): Define and pass as part of
+ SUPPORT_FILES to submakes.
+
+Fri Aug 4 13:04:36 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (GDB_SUPPORT_DIRS): Add utils.
+ (DEVO_SUPPORT): Add mpw-README, mpw-build.in, mpw-config.h and
+ mpw-configure.
+
+Wed Aug 2 16:32:40 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * configure.in (appdirs): Use =, not ==, in test expression when
+ trying to build the text to print in the warning message for
+ Solaris users.
+
+Mon Jul 31 09:56:18 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * cfg-ml-com.in (z8k-*-coff): Add 'std' multilib build.
+
+Fri Jul 28 00:16:31 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config.guess: Recognize lynx-2.3.
+
+Thu Jul 27 15:47:59 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * config.sub (z8ksim): Deleted
+ (z8k-*-coff): New, this is the one true name of the target.
+
+Thu Jul 27 14:33:33 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * cfg-ml-pos.in (dotdot): Work around SunOS sed bug.
+
+Thu Jul 27 13:31:05 1995 Fred Fish (fnf@cygnus.com)
+
+ * config.guess (*:Linux:*:*): First try asking the linker what the
+ default object file format is (elf, aout, or coff). Then if this
+ fails, try previous methods.
+
+Thu Jul 27 11:28:17 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in: Don't build newlib for *-*-vxworks5.1.
+
+Thu Jul 27 11:18:47 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * configure.in: Don't build newlib for a29k-*-vxworks5.1.
+ * test-build.mk: Add setting of --with-headers for a29k-vxworks5.1.
+
+Tue Jul 25 21:25:39 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * cfg-ml-pos.in (MULTITOP): Trim excess trailing "/.".
+
+Fri Jul 21 10:41:12 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * cfg-ml-com.in: New file.
+ * cfg-ml-pos.in: New file.
+
+Wed Jul 19 00:37:27 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * COPYING.NEWLIB: Add HP free copyright to list.
+
+Tue Jul 18 10:58:51 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config.sub: Recognize -eabi* for the system, not just -eabi.
+
+Mon Jul 3 13:44:51 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * Makfile.in (DLLTOOL_FOR_TARGET): New name, pass it down.
+ * config.sub, configure.in (win32): New target and host.
+
+Wed Jun 28 23:57:08 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * configure.in: Add i386-pe configuration.
+
+Fri Jun 23 14:28:44 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-build.in (install): Install GDB after LD.
+
+Thu Jun 22 17:10:53 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in (elf/mips.h): Always forward-include, needed
+ for GDB to build.
+
+Wed Jun 21 15:17:30 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * testsuite: New directory for customer acceptance and whole tool
+ chain tests.
+
+Wed Jun 21 16:50:29 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * configure: If per-host line isn't found, but AC_OUTPUT is found
+ and a configure script exists, run it instead.
+
+Thu Jun 15 21:09:24 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * config.guess: Update from FSF, for alpha-dec-winnt3.5 and Crays.
+
+Tue Jun 13 21:43:27 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * configure: Set build_{cpu,vendor,os,alias} to host values when
+ --build isn't specified.
+
+Mon Jun 5 18:26:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * Makefile.in (PICFLAG, PICFLAG_FOR_TARGET): New macros.
+ (FLAGS_TO_PASS): Pass them.
+ (EXTRA_TARGET_FLAGS): Ditto.
+
+ * config/m?-*pic: Define PICFLAG* instead of LIB*FLAGS*.
+
+Wed May 31 22:27:42 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * Makefile.in (all-libg++): Depend on all-libstdc++.
+
+Thu May 25 22:40:59 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in (noconfigdirs): Enable all packages for
+ i386-unknown-netbsd.
+
+Sat May 20 13:22:31 1995 Angela Marie Thomas <angela@cirdan.cygnus.com>
+
+ * configure.in (noconfigdirs): Don't configure tk for i386-go32
+ hosted builds (DOS builds)
+
+Thu May 18 18:08:49 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ Changes for ARM based on patches from Richard Earnshaw:
+ * config.sub: Handle armeb and armel.
+ * configure.in: Omit arm linker only for riscix.
+
+Thu May 11 17:23:26 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * config.guess: Update from FSF.
+
+Tue May 9 15:52:05 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config.sub: Recognize powerpcle as the little endian varient of
+ the PowerPC. Recgonize ppc as a PowerPC variant, and ppcle as a
+ powerpcle variant. Convert pentium into i586, not i486. Add p5
+ alias for i586. Map new x86 variants p6, k5, nexgen into i586
+ temporarily.
+
+Tue May 2 16:29:41 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * configure.in (hppa*-*-lites*): Treat like hppa*-*-*elf*.
+
+Sun Apr 30 21:38:09 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config.sub: Accept -lites* as a basic system type.
+
+Thu Apr 27 11:33:29 1995 Michael Meissner (meissner@cygnus.com)
+
+ * config.guess (*:Linux:*:*): Check for whether the pre-BFD linker is
+ installed, and if so return linuxoldld as the system name.
+
+Wed Apr 26 10:59:02 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config.guess: Add hppa1.1-hp-lites support.
+
+Tue Apr 25 11:08:11 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * configure.in: Don't build newlib for m68k-vxworks5.1.
+
+Wed Apr 19 17:02:43 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * configure.in (mips-sgi-irix6): Use mh-irix5.
+
+Fri Apr 14 15:21:17 1995 Doug Evans <dje@chestnut.cygnus.com>
+
+ * Makefile.in (all-gcc): Depend on all-ld (for libgcc1-test).
+
+Wed Apr 12 16:06:01 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * test-build.mk: Enable building of shared libraries on IRIX 5 and
+ OSF/1. Fix compiler flags.
+ * build-all.mk: Support Linux and OSF/1 3.0. Fix compiler flags.
+
+Tue Apr 11 18:55:40 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * configure.in: Recognize --with-newlib.
+ (sparc-*-sunos4*): Build sim, dejagnu, expect, tcl if cross target.
+
+Mon Apr 10 14:38:20 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Makefile.in: move {all,check,install}-gdb from *_MODULES
+ to *_X11_MODULES due to gdbtk needing X include files et al.
+
+Mon Apr 10 11:42:22 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ Merge in support for Mac MPW as a host.
+ (Old change descriptions retained for informational value.)
+
+ * mpw-config.in: Add generic include forwards for cpu-specific
+ include files in aout and elf directories.
+
+ * mpw-configure: Added copyright.
+ * mpw-config.in: Check for presence of required build tools.
+ (target_libs): Add newlib.
+ (target_tools): Add examples.
+ (Read Me): Generate as "Read Me for MPW" instead.
+ * mpw-build.in: Base sub-builds on all-foo instead of do-foo.
+ (all-byacc, do-byacc, all-flex, do-flex, do-newlib): New actions.
+ (do-gas, do-gcc, do-gdb, do-ld): Build Version.r first.
+
+ * mpw-configure: Remove subdir-specific makefile hackery,
+ delete mk.tmp after using it.
+
+ * mpw-build.in (all): Display start and end times.
+
+ * mpw-configure (host_canonical): Set.
+ (target_cpu): Always add to makefiles.
+ (ARCHDEFS, EMUL): Add to makefile only if nonempty.
+ (TM_FILE, XM_FILE, NM_FILE): No longer add to makefile.
+ (mpw-mh-mpw): Look for in srcdir and srcroot.
+ Use sed instead of mpw-edit-prefix to edit prefix definitions.
+
+ * mpw-build.in: (install-only): New target.
+
+ * mpw-configure (host_alias, target_alias): Rename from hostalias
+ and targetalias, add into generated Makefile.
+ (mk.tmp): If present, add into generated Makefile.
+ * mpw-build.in (all-gas): Build config.h first before gas proper.
+
+ * mpw-configure (config.status): Write only if changed.
+ * mpw-config.in (readline): Configure it (not built, just used for
+ definitions).
+
+ * mpw-config.in (elf/mips.h): Add a forward include.
+
+ * mpw-config.in: Forward-include most .h files in include into
+ extra-include.
+ (readline): Don't build.
+ mpw-build.in (install): Install GDB.
+
+ * mpw-configure (prefix, mpw_prefix): Handle it.
+ * mpw-config.in (mmalloc, readline): Don't configure.
+ * mpw-build.in (thisscript): Rename to ThisScript.
+ Use mpw-build instead of BuildProgram everywhere.
+ (mmalloc, readline): Don't build.
+ * mpw-README: New file, basic documentation about the MPW port.
+
+ * mpw-config.in: Use forward-include to create include files.
+
+ * mpw-configure: Add more things to the top of each configured
+ Makefile, including contents of config/mpw-mh-mpw.
+ * mpw-config.in (extra-include): Create this directory and fill it
+ with Posix-like include files when configuring.
+
+ * config.sub (apple, mac, mpw): Add various aliases.
+
+ * mpw-build.in: New file, top-level build script fragment for MPW.
+ * mpw-configure: New file, configure script for MPW.
+ * mpw-config.in: New file, config fragment for MPW.
+
+Fri Apr 7 19:33:16 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in (host_libs): Remove glob, since it is gone from the
+ sources.
+
+Fri Mar 31 11:36:17 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Makefile.in: define empty GDB_NLM_DEPS var.
+
+ * configure.in(target_makefile_frag): use config/mt-netware
+ for netware targets.
+
+Thu Mar 30 13:51:43 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config.sub: Merge in recent FSF changes. Remove linux special
+ cases.
+
+Tue Mar 28 14:47:34 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ build-all.mk,config/mh-solaris: revert these two changes:
+
+ Tue Mar 30 10:03:09 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * build-all.mk: Use CC=cc -Xs on Solaris.
+
+ Mon Mar 29 19:59:26 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config/mh-solaris: SunPRO C needs -Xs to be able to get a
+ working xmakefile for Emacs.
+
+Tue Mar 21 10:43:32 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * glob/*: Removed. Schauer's 24 Feb 1994 readline change made us
+ stop using it.
+ * Makefile.in: Nuke all references to glob subdirectory.
+
+Thu Mar 16 13:35:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * configure.in: Fix --enable-shared logic in per-host.
+
+Mon Mar 13 12:33:15 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in (*-hp-hpux[78]*): Use mh-hpux8.
+
+Mon Mar 6 10:21:58 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in (noconfigdirs): Don't build gas on AIX, for
+ powerpc*-*-aix* as well as for rs6000*-*-aix*.
+
+Wed Mar 1 12:51:53 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Fix --cache-file to work if the file argument is a
+ relative path.
+
+Tue Feb 28 17:36:07 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: If the --cache-file is used, pass it down to
+ configure in subdirectories.
+
+Mon Feb 27 12:52:46 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * config.sub: add vxworks29k configuration.
+
+Fri Feb 10 16:12:26 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (taz): Do "diststuff" part quietly.
+
+Sun Feb 5 14:16:35 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config.sub: Mini-merge with gcc/config.sub.
+
+Sat Feb 4 12:11:35 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * config.guess (IRIX): Sed - to _.
+
+Fri Feb 3 11:54:42 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (source-vault, binary-vault): New targets.
+
+Thu Jan 26 13:00:11 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config.sub: Recognize -eabi as a basic system type.
+
+Thu Jan 12 13:13:23 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * configure.in (enable_shared stuff): Fix typo.
+
+Thu Jan 12 01:36:51 1995 deanm@medulla.LABS.TEK.COM (Dean Messing)
+
+ * Makefile.in (BASE_FLAGS_TO_PASS): Fix typo in passing LIBCXXFLAGS*.
+
+Wed Jan 11 16:29:53 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * Makefile.in (LIBCXXFLAGS_FOR_TARGET): Add -fno-implicit-templates.
+
+Mon Jan 9 12:48:01 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * configure.in (rs6000-*-*): Don't build gas.
+
+Wed Jan 4 23:53:49 1995 Ian Lance Taylor <ian@tweedledumb.cygnus.com>
+
+ * Makefile.in: Use /x/x/ instead of /brokensed/brokensed/, to
+ reduce command line length.
+ (AS_FOR_TARGET): Check for as.new, not Makefile.
+ (NM_FOR_TARGET): Check for nm.new, not Makefile.
+
+Wed Jan 4 13:02:39 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * config.guess: Merge from FSF.
+
+Thu Dec 15 17:11:37 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * configure: Don't use $ when handling program_suffix.
+
+Mon Dec 12 12:09:37 1994 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Configure tk for hppa/hpux.
+
+Fri Dec 2 15:55:38 1994 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in (LIBGXX_SUPPORT_DIRS): Add libstdc++.
+
+Tue Nov 29 19:37:56 1994 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in: Move -fno-implicit-template from CXXFLAGS
+ to LIBCXXFLAGS. Tests are better run without it.
+
+Wed Nov 23 10:29:25 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * Makefile.in (all-ispell): Depend on all-emacs19 instead of all-emacs.
+
+Mon Nov 21 11:14:01 1994 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in (*-*-netware*): Don't configure xiberty.
+
+Mon Nov 14 08:49:15 1994 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Remove tk from native_only list.
+
+Fri Nov 11 15:31:26 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * build-all.mk: Add mips-ncd-elf target to sun4 targets
+ for special NCD build.
+
+Mon Nov 7 20:58:17 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (DEVO_SUPPORT): Remove configure.bat and
+ makeall.bat, they're only useful for binutils snapshots.
+ (binutils.tar.gz, gas+binutils.tar.gz): Add configure.bat and
+ makeall.bat to specified SUPPORT_FILES.
+
+Mon Nov 7 17:25:18 1994 Bill Cox (bill@cirdan.cygnus.com)
+
+ * build-all.mk: Add Ericsson targets to sun4 and solaris
+ hosts. Add BNR's sun4 target to solaris host, so their
+ build-from-source will be tested in-house first.
+
+Sat Nov 5 18:43:30 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+
+ * Makefile.in (LIBCFLAGS): New variable.
+ (CFLAGS_FOR_TARGET): Ditto.
+ (LIBCFLAGS_FOR_TARGET): Ditto.
+ (LIBCXXFLAGS): Ditto.
+ (CXXFLAGS_FOR_TARGET): Ditto.
+ (LIBCXXFLAGS_FOR_TARGET): Ditto.
+ (BASE_FLAGS_TO_PASS): Pass them.
+ (EXTRA_TARGET_FLAGS): Ditto.
+
+ * configure.in, config/m[th]-*pic: Support --enable-shared.
+
+Sat Nov 5 15:44:00 1994 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * configure.in (target_libs): Include libstdc++ again.
+ * config.guess: Update from FSF (for FreeBSD).
+
+Thu Nov 3 16:32:30 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (DEVO_SUPPORT): Include configure.bat and
+ makeall.bat.
+ (DISTDOCDIRS): Add `etc'.
+ (ETC_SUPPORT_PFX): New variable.
+ (taz): Include anything from etc starting with a word in
+ ETC_SUPPORT_PFX.
+
+Wed Oct 26 16:19:35 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config.sub: Update for recent FSF changes. Remove obsolete
+ h8300hds entry. Add -windows* and -osx as basic os. Minor
+ spacing changes.
+
+Thu Oct 20 18:41:56 1994 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * configure.in (target_libs): Remove libstdc++ for libg++-2.6.1.
+
+ * config.guess: Merge with FSF.
+ * configure.in: Match on i?86-ncr-sysv4.3, not i?86-ncr-sysv43.
+
+Thu Oct 20 19:26:56 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * configure: Since the "trap 0" handler will override the exit
+ status on many systems, only use it for "exit 1", and make it set
+ a non-zero exit status; reset it before "exit 0". Also, check
+ exit status of config.sub, and error out if it failed.
+
+Wed Oct 19 18:49:55 1994 Rob Savoye (rob@cygnus.com)
+
+ * Makefile.in: (ALL_TARGET_MODULES,INSTALL_TARGET_MODULES) Build
+ and install libgloss.
+
+Tue Oct 18 15:25:24 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * Makefile.in (all-binutils): Depend upon all-byacc.
+
+ * configure.in: Don't build emacs on Irix 5.
+
+Mon Oct 17 16:22:12 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * configure.in (*-*-netware*): Add libio.
+
+Thu Oct 13 15:51:20 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+
+ * Makefile.in (ALL_TARGET_MODULES): Add libstdc++.
+ (CHECK_TARGET_MODULES): Ditto.
+ (INSTALL_TARGET_MODULES): Ditto.
+ (TARGET_LIBS): Ditto.
+ (all-libstdc++): Note dependencies.
+
+Thu Oct 13 01:43:08 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (BINUTILS_SUPPORT_DIRS): Add gas.
+
+Tue Oct 11 12:12:29 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+
+ * Makefile.in (CXXFLAGS): Use -fno-implicit-templates instead of
+ -fexternal-templates.
+
+ * configure.in (target_libs): Add libstdc++.
+ (noconfigdirs): Add libstdc++ as appropriate.
+
+Thu Oct 6 18:00:54 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess: Update from FSF.
+
+Tue Oct 4 12:05:42 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * configure: Use ${config_shell} when running ${configsub}.
+
+Mon Oct 3 14:28:34 1994 Doug Evans <dje@canuck.cygnus.com>
+
+ * config.sub: No longer recognize h8300h.
+
+Mon Oct 3 12:40:54 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config.sub: Remove extraneous differences between config.sub and
+ gcc/config.sub.
+
+Sat Oct 1 00:23:12 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (DISTSTUFFDIRS): Add gas.
+
+Thu Sep 22 19:04:55 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * COPYING.NEWLIB: New file.
+
+Mon Sep 19 18:25:40 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess (HP-UX): Patch from Harlan Stenn
+ <harlan@landmark.com> to also emit release level.
+
+Wed Sep 7 13:15:25 1994 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * config.guess (sun4*:SunOS:*:*): Change '-JL' to '_JL'.
+
+Tue Sep 6 23:23:18 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.sub: Merge nextstep cleanup from FSF.
+
+Mon Sep 5 05:01:30 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * configure.in (arm-*-*): Don't configure ld for this target.
+
+Thu Sep 1 09:35:00 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * configure.in (*-*-netware): don't configure libg++, libio,
+ librx, or newlib.
+
+Wed Aug 31 13:52:08 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure.in (alpha-dec-osf*): Use osf*, not osf1*. Don't
+ configure ld--it works, but it doesn't support shared libraries.
+
+Sun Aug 28 18:13:45 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess (*-unknown-freebsd*): Get rid of possible
+ trailing "(Release)" in version string.
+ Patch from Paul Richards <paul@isl.cf.ac.uk>.
+
+Sat Aug 27 15:00:49 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess: Fix i486-ncr-sysv43 -> i486-ncr-sysv4.3.
+ Fix type: *-next-neststep -> *-next-nextstep.
+
+ * config.guess: Merge from FSF:
+
+ Fri Aug 26 18:45:25 1994 Philippe De Muyter (phdm@info.ucl.ac.be)
+
+ * config.guess: Recognize powerpc-ibm-aix3.2.5.
+
+ Wed Apr 20 06:36:32 1994 Philippe De Muyter (phdm@info.ucl.ac.be)
+
+ * config.guess: Recognize UnixWare 1.1 (UNAME_SYSTEM is SYSTEM_V
+ instead of UNIX_SV for UnixWare 1.0).
+
+Sat Aug 27 01:56:30 1994 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (all-gdb): Add dependencies on all-gcc and all-ld
+ to make gdb/nlm/* build after the compiler and linker.
+
+Fri Aug 26 14:30:05 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess (netbsd, freebsd, linux): Accept any machine,
+ not just i[34]86.
+ (m68k-atari-sysv4): Relocate to match FSF version.
+
+ * config.guess: More merges from the FSF:
+
+ Add a space before function call or macro invocation.
+
+ Tue May 10 16:53:55 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * config.guess: Add trap cmd to remove dummy.c and dummy when
+ interrupted.
+
+ Wed Apr 20 18:07:13 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * config.guess (dummy.c): Redirect stderr for `hostinfo' command.
+ (dummy): Redirect stderr from compilation of dummy.c.
+
+ Sat Apr 9 14:59:28 1994 Christian Kranz (kranz@sent5.uni-duisburg.de)
+
+ * config.guess: Distinguish between NeXTStep 2.1 and 3.x.
+
+Fri Aug 26 13:42:20 1994 Ken Raeburn (raeburn@kr-laptop.cygnus.com)
+
+ * configure: Accept and ignore --cache*, for compatibility with
+ new autoconf.
+
+Fri Aug 26 13:05:27 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess: Merge from FSF:
+
+ Thu Aug 25 20:28:51 1994 Richard Stallman <rms@mole.gnu.ai.mit.edu>
+
+ * config.guess (Pyramid*:OSx*:*:*): New case.
+ (PATH): Add /.attbin at end for finding uname.
+ (dummy.c): Handle i860-alliant-bsd. Follow whitespace conventions.
+
+ Wed Aug 17 18:21:02 1994 Tor Egge (tegge@pvv.unit.no)
+
+ * config.guess (M88*:DolphinOS:*:*): New case.
+
+ Thu Aug 11 17:00:13 1994 Stan Cox (coxs@dg-rtp.dg.com)
+
+ * config.guess (AViiON:dgux:*:*): Use TARGET_BINARY_INTERFACE
+ to select whether to use ELF or COFF.
+
+ Sun Jul 24 16:20:53 1994 Richard Stallman <rms@mole.gnu.ai.mit.edu>
+
+ * config.guess: Recognize i860-stardent-sysv and i860-unknown-sysv.
+
+ Sun May 1 10:23:10 1994 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * config.guess: Guess the OS version for HPUX.
+
+ Tue Mar 1 21:53:03 1994 Karl Heuer (kwzh@hal.gnu.ai.mit.edu)
+
+ * config.guess (UNAME_VERSION): Recognize aix3.2.4 and aix3.2.5.
+
+Fri Aug 26 11:19:08 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure.in: Recognize --with-headers, --with-libs, and
+ --without-newlib.
+ * Makefile.in (all-xiberty): Depend upon all-ld.
+
+Wed Aug 24 12:36:50 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure.in: Change i[34]86 to i[345]86.
+
+Mon Aug 22 10:58:33 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure (version): A few more tweaks to help message.
+
+Fri Aug 19 12:40:25 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * Makefile.in: Remove (for now) librx as a host library,
+ now that we're building it for target.
+
+Fri Aug 19 10:49:17 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure: Fix up help message; from karl@owl.hq.ileaf.com
+ (Karl Berry).
+
+Tue Aug 16 16:11:08 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * configure.in: Also configure librx.
+
+Mon Aug 15 16:51:45 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * Makefile.in: Update various rules to reflect that librx
+ is now needed for libg++.
+
+Fri Aug 12 18:07:21 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config.sub: Accept mips64orion and mips64orionel as a CPU name.
+
+Mon Aug 8 11:36:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * configure.in: Configure the examples directory.
+
+Thu Aug 4 16:12:36 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure: Simplify Jun 2 1994 change.
+
+Wed Aug 3 04:58:16 1994 D. V. Henkel-Wallace (gumby@cygnus.com)
+
+ * change CC to /usr/latest/bin/gcc for lynx host builds, since
+ /bin/gcc isn't good enough to build gcc.
+
+Wed Jul 27 09:07:14 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (GDB_SUPPORT_FILES): Remove
+ (setup-dirs-gdb, gdb.tar.gz, make-gdb.tar.gz): Remove old rules.
+ (gdb.tar.gz): Add new rule to use standard distribution building
+ mechanism.
+
+Mon Jul 25 11:10:06 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in: Warn about use of /usr/ucb/cc on Solaris. From
+ Bill Cox <bill@cygnus.com>.
+
+Sat Jul 23 12:19:46 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess: Recognize ISC. Patch from kwzh@gnu.ai.mit.edu.
+
+Fri Jul 22 17:53:59 1994 Stu Grossman (grossman@cygnus.com)
+
+ * configure: Search current dir first in .gdbinit.
+
+Fri Jul 22 11:28:30 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.sub: Recognize freebsd (merged from gcc config.sub).
+
+Thu Jul 21 14:10:52 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.sub: Refer to NeXT's operating system as nextstep.
+
+ * config.sub (case $basic_machine): Re-order the cases, to match
+ the order in the FSF version (which is mostly alphabethical).
+ Merge in some additions and changes from the FSF.
+
+Sat Jul 16 12:03:08 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config.guess: Recognize m68k-atari-sysv4 and m88k-harris-csux7.
+ * config.sub: Recognize cxux7.
+ * configure.in: Use mh-cxux for m88k-harris-cxux*.
+
+Mon Jul 11 14:37:39 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.sub: Fix typo powerpc -> powerpc-*.
+
+Sat Jul 9 13:03:43 1994 Michael Tiemann (tiemann@blues.cygnus.com)
+
+ * Makefile.in: `all-emacs19' depends on `all-byacc'.
+
+ * Makefile.in: Add all-emacs19 and install-emacs19 rules (in
+ parallel with all-emacs and install-emacs). Top-level command
+ `make all-emacs19 CC=gcc' now behaves as `make all-emacs CC=gcc'.
+
+Thu Jun 30 16:53:42 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * test-build.mk ($(host)-stamp-stage2-installed): Remove
+ $(relbindir)/make before doing ``make install'', and use
+ $(GNU_MAKE) while doing it. Avoids problem on SunOS with
+ installing over running make binary.
+ ($(host)-stamp-stage3-installed): Likewise.
+
+Tue Jun 28 13:43:25 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.guess: Recognize Mach.
+
+Mon Jun 27 16:41:14 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure: Check ${exec_prefixoption}, not ${exec_prefix}, to
+ see whether --exec-prefix was used.
+
+Sun Jun 26 21:15:54 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * README: Explicitly mention libg++/README. (Zoo's idea.)
+
+Tue Jun 21 12:45:55 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Add all-librx target similar to all-libproc.
+
+Wed Jun 8 23:11:55 1994 Stu Grossman (grossman@cygnus.com)
+
+ * config.guess: Rearrange tests for Alpha-OSF1 to properly deal
+ with post 1.2 uname bogosity.
+
+Thu Jun 9 00:27:59 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure: Remove temporary files on receipt of a signal.
+
+Tue Jun 7 12:06:24 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure: If there is a package_makefile_frag, remove
+ ${subdir}/Makefile.tem after copying it in.
+
+Mon Jun 6 21:35:02 1994 D. V. Henkel-Wallace (gumby@cygnus.com)
+
+ * build_all.mk: support rs6000 lynx identifies itself as
+ rs6000-lynx-lynxos2.2.2. Also, use /usr/cygnus/progressive/bin/gcc
+ since /bin/gcc is too feeble to compile a modern gcc.
+
+Mon Jun 6 16:06:34 1994 Karen Christiansen (karen@cirdan.cygnus.com)
+
+ * brought devo/test-build.mk update-to-date with progressive/
+ test-build.mk. Add lynx targets and hppa flag info.
+
+Sat Jun 4 17:23:54 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * configure.in: Use mh-ncrsvr43. Patch from
+ Tom McConnell <tmcconne@sedona.intel.com>.
+
+Fri Jun 3 17:47:24 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess (i386-unknown-bsdi): No longer need to
+ check #if defined(__bsdi__) && defined(__i386__).
+
+Thu Jun 2 18:56:46 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure: Set program_transform_nameoption correctly.
+
+Thu Jun 2 10:57:06 1994 Karen Christiansen (karen@cirdan.cygnus.com)
+
+ * brought build-all.mk update-to-date with progressive build-all.mk,
+ added new targets and hppa info.
+
+Thu Jun 2 00:12:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure: If config.guess result is a prefix of the user
+ specified target, assume a native build and use the user specified
+ target as the host alias. Remove SunOS patch suffix removal hack.
+ * configure.in: Remove SunOS patch suffix removal hack.
+
+ * Makefile.in (CROSS_CHECK_MODULES): Remove check-flex, since it's
+ in NATIVE_CHECK_MODULES.
+
+Wed Jun 1 10:49:41 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * Makefile.in: Rename HOST_ONLY to NATIVE.
+ * configure: Delete SunOs patch suffix from host_canonical
+ and build_canonical variables that are prepended to Makefiles.
+ * configure.in: Add comments for easier maintenance.
+
+Tue May 31 19:39:47 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Add all-libproc target similar to all-gui.
+
+Tue May 31 17:16:33 1994 Tom Lord (lord@cygnus.com)
+
+ * Makefile.in (CHECK_MODULES): split into
+ HOST_ONLY_CHECK_MODULES and CROSS_CHECK_MODULES.
+
+Tue May 31 16:36:36 1994 Paul Eggert (eggert@twinsun.com)
+
+ * config.guess (i386-unknown-bsdi): New system to guess.
+
+Wed May 25 16:47:10 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Add all-gui target (but not yet build by "all").
+
+Thu May 26 08:53:19 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * config.sub: Move deletion of patch suffix from here...
+ * configure.in: To here, at Ian's suggestion. The top-
+ level scripts might need to know of a patch level.
+
+Wed May 25 09:15:54 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * config.sub: Strip off patch suffix so rtl is recognized
+ as a sunos4.1.3 machine, even though it's been patched.
+
+Fri May 20 08:25:49 1994 Steve Chamberlain (sac@deneb.cygnus.com)
+
+ * Makefile.in (INSTALL_LAST): Delete.
+ (INSTALL_DOSREL): New.
+
+Thu May 19 17:12:12 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in: Use ld for i[34]86-*-sysv4* and sparc-*-solaris2*.
+ Don't set use_gnu_ld to no for *-*-sysv4; that only controls
+ whether we pass down --with-gnu-ld anyhow.
+
+Thu May 19 09:29:12 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * Makefile.in (INSTALL_LAST): Change operation so it works
+ on more flavors of make.
+ * configure.in (go32): Don't build libg++ or libio.
+
+Fri May 13 13:28:34 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * Makefile.in (Move HOST_PREFIX_1 and friends up so
+ they can be overriden by templates.
+
+Sat May 7 16:46:44 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * configure.in (target==go32): Don't build gdb.
+ * dosrel: New directory.
+
+Fri May 6 14:19:25 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * configure.in (host==go32): Configure dosrel too.
+ * Makefile.in (INTALL_TARGET): Call INSTALL_LAST last.
+ (HOST_CC, HOST_PREFIX, HOST_PREFIX_1): Undefine, they should
+ be set by incoming names or templates.
+ (INSTALL_LAST): New rule.
+ * config/mh-go32: New fragment.
+
+Thu May 5 17:35:05 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config.sub (sparclitefrw, sparclitefrwcompat): Don't set the os.
+
+Thu May 5 20:06:45 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/mh-lynxrs6k: Renamed from mh-lynxosrs6k, to make it
+ unique in 8.3 naming schemes.
+ * configure.in (appdirs): New variable. Currently empty, but will
+ be used in gas distribution. If nonempty, lists a set of
+ directories at least one of which must get configured, or top
+ level configuration is considered to have failed.
+ (rs6000-*-lynxos*): Use new file name.
+
+Thu May 5 13:38:36 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ Eliminate XTRAFLAGS.
+ * Makefile.in (CC_FOR_TARGET): If newlib exists, refer to the
+ newlib include files using -idirafter, and also use -nostdinc.
+ (CXX_FOR_TARGET): Likewise.
+ (XTRAFLAGS): Removed.
+ (BASE_FLAGS_TO_PASS): Remove XTRAFLAGS_FOR_TARGET.
+ (EXTRA_HOST_FLAGS): Remove XTRAFLAGS.
+ (EXTRA_TARGET_FLAGS, EXTRA_GCC_FLAGS): Likewise.
+ ($(DO_X)): Don't pass down XTRAFLAGS.
+
+Thu May 5 00:16:36 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * configure.in (mips*-dec-bsd*): New target; do build linker.
+ (mips*-*-bsd*): New target; don't build linker.
+
+Wed May 4 20:10:10 1994 D. V. Henkel-Wallace (gumby@cygnus.com)
+
+ * configure.in: support rs6000-*-lynxos* configuration.
+ support sunos4 as a cross target.
+
+ * config.sub: look for lynx*, not lynx since the OS version may
+ legitimately be part of the name.
+
+Tue May 3 21:48:11 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * configure.in (i[34]86-*-sco*): Move to be with other i386
+ targets.
+ (romp-*-*): New target. Skip various binary utilities.
+ (vax-*-*): New target. Don't build newlib.
+ (vax-*-vms): Renamed from *-*-vms. Don't build opcodes or newlib.
+
+Thu Apr 28 15:03:05 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * configure.in: Only set host_makefile_frag if config
+ directory exists.
+
+Wed Apr 27 12:14:30 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * install.sh: If $dstdir exists, don't check whether each
+ component does.
+
+Tue Apr 26 18:11:33 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * test-build.mk (HOLES): Add sleep; used by rcs/src/conf.sh.
+
+Mon Apr 25 15:06:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * configure.in (*-*-lynxos*): Don't configure newlib for either
+ native or cross Lynx.
+
+Sat Apr 16 11:58:16 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * config.sub (sparc64-elf): Fix os.
+ (z8k): Remove duplicate.
+
+Thu Apr 14 23:33:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (gcc-no-fixedincludes): Touch gcc/include/fixed, not
+ gcc/stmp-fixproto, to try to prevent fixproto from being run.
+
+Wed Apr 13 15:14:52 1994 Bill Cox (bill@cygnus.com)
+
+ * configure: Make file links cleanly even if Lynx fails on
+ an NFS symlink (at least fail cleanly).
+
+Mon Apr 11 10:58:56 1994 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * test-build.mk (CC): For mips-sgi-irix4, change -XNh1500 to
+ -XNh2000.
+
+Sat Apr 9 15:10:45 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * configure: Unknown options are fatal again.
+
+Fri Apr 8 12:01:41 1994 David J. Mackenzie (djm@cygnus.com)
+
+ * configure: Ignore --x-includes and --x-libraries, for Autoconf
+ compatibility.
+
+Thu Apr 7 17:31:43 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * build-all.mk: Add `clean' target.
+
+Wed Apr 6 20:44:56 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config.guess: Add SINIX support.
+ * configure.in: Add mips-*-sysv4* support.
+
+Mon Apr 4 17:41:44 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * build-all.mk: Document all useful targets.
+ If canonhost is sparc-sun-solaris2.3, change it to sparc-sun-solaris2.
+ If canonhost is mips-sgi-irix4.0.5H, change it to mips-sgi-irix4.
+
+Thu Mar 31 04:55:57 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * configure: Support --silent, --quiet.
+
+Wed Mar 30 21:37:38 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * configure: Support --disable-FEATURE.
+
+Tue Mar 29 19:15:05 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.guess: Recognize NCR running SVR4.3.
+
+Mon Mar 28 14:55:15 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess: Make BSDI generate i386-unknown-bsd386.
+ Patch from Paul Eggert <eggert@twinsun.com>.
+
+Mon Mar 28 12:54:52 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in (powerpc-*-aix*): Treat like rs6000-*-*.
+
+Sat Mar 26 11:25:48 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * configure: Make unrecognized options give nonfatal warnings
+ instead of fatal errors, and pass them to any subdirectory
+ configures in case they recognize them.
+ Make --x equivalent to --with-x.
+
+Fri Mar 25 21:52:10 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * configure: Add --enable-* options. Clean up usage message and
+ some comments.
+
+Thu Mar 24 09:12:53 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * Makefile.in (NM_FOR_TARGET): Build tree version is now nm.new.
+
+Sun Mar 20 11:28:22 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * configure.in (hppa*-*-*): Enable binutils.
+
+Sat Mar 19 11:50:16 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.sub: Recognize cisco.
+
+Fri Mar 18 16:42:32 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * Makefile.in (CXXFLAGS): Add -fexternal-templates.
+
+Tue Mar 15 11:25:55 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.guess: about target *-hitachi-hiuxwe2, don't print more
+ than one configuration name. Add comment.
+
+Sun Mar 6 23:13:38 1994 Hisashi MINAMINO (minamino@sra.co.jp)
+
+ * config.guess: about target *-hitachi-hiuxwe2, fixed
+ machine guessing order. [Hitachi's CPU_IS_HP_MC68K
+ macro is incorrect.]
+
+Sun Mar 13 09:10:08 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (TAGS): Just build TAGS in each subdirectory, rather
+ than the "make ls" stuff which used to be here.
+
+Fri Mar 11 12:52:39 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess: Recognize i[34]86-unknown-freebsd.
+ From Shawn M Carey <smcarey@rodan.syr.edu>.
+
+Thu Mar 3 14:24:21 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * configure.in (noconfigdirs for alpha): Remove libg++ and libio.
+
+Wed Mar 2 13:28:48 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * config.guess: Check for ptx.
+
+Mon Feb 28 16:46:50 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * config.sub: Add os9k checking.
+
+Thu Feb 24 07:09:04 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config.guess: Handle OSF1 running on HPPA processors
+
+Fri Feb 18 14:14:00 1994 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * configure: If subdir configure fails, print out a message with
+ subdirectory name, in case subdir's configure code didn't identify
+ itself.
+
+Fri Feb 18 12:50:15 1994 Doug Evans (dje@cygnus.com)
+
+ * configure.in: Remove embedded newlines from configdirs.
+ Avoid mismatches of substrings. Fix matching strings at end
+ of configdirs.
+
+Fri Feb 11 15:33:33 1994 Stu Grossman (grossman at cygnus.com)
+
+ * config.guess: Add Lynx/rs6000 config support.
+
+Tue Feb 8 13:41:09 1994 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * configure.in (alpha-dec-osf1*, alpha*-*-*): Build gas.
+
+Mon Feb 7 15:42:36 1994 Jeffrey A. Law (law@cygnus.com)
+
+ * configure.in (hppa*-*-osf*): Treat this just like most other
+ PA configurations (eg no binutils or ld).
+ (hppa*-*-*elf*): These configurations have binutils and ld.
+
+Sun Feb 6 16:35:07 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config.sub (hiux): Fix typo. From m-kasahr@sramhc.sra.co.JP.
+
+Sat Feb 5 01:00:33 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in (rs6000-*-*): Build gas.
+
+Wed Feb 2 13:57:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * Makefile.in: Avoid bug in losing hpux sed.
+
+Wed Feb 2 14:53:05 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in, test-build.mk: Remove MUNCH_NM; it was only needed
+ for GDB and GDB has been fixed to not need it.
+
+Mon Jan 31 18:40:55 1994 Stu Grossman (grossman at cygnus.com)
+
+ * config/mh-lynxosrs6k: Account for lack of ranlib!
+
+Sun Jan 30 17:58:06 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config.guess: Recognize vax hosts.
+
+Fri Jan 28 15:29:38 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * configure (while loop): Don't use "break 2" inside case
+ statement -- the case statement isn't an enclosing loop.
+
+Mon Jan 24 18:40:06 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess: Clean up NeXT support, to allow nextstep
+ on Intel machines. Make OS be nextstep.
+
+Sun Jan 23 18:47:22 1994 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+ * config.guess: Add alternate forms for Convex.
+
+Thu Jan 20 16:13:41 1994 Stu Grossman (grossman at cygnus.com)
+
+ * configure: Completely rewrite option processing. Take
+ advantage of pattern-matching to avoid invoking test frequently.
+ Also clean up host and target defaulting logic.
+
+Mon Jan 17 15:06:56 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * Makefile.in: Replace all occurrances of "rootme" with "r" and
+ "$${rootme}" with "$$r", to increase the likelihood that the do-*
+ commands (plus user environment) will fit SCO limits.
+
+Thu Jan 6 11:20:57 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in: Don't issue warnings about directories which are
+ not being configured if -norecursion is set. Correct test for
+ --with-gnu-as and --with-gnu-ld to not get confused by substring
+ matches.
+
+ * configure.in: Don't build gas for alpha-dec-osf1*.
+
+Tue Jan 4 17:10:19 1994 Stu Grossman (grossman at cygnus.com)
+
+ * configure: Back out Per's change of 12/19/1993. It changes the
+ behavior of configure in unexpected and confusing ways.
+
+ Also, use different delim char when calculating
+ program_transform_name so that the name can contain slashes.
+
+Sat Jan 1 13:45:31 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * configure.in, config.sub: Add support for VSTa micro-kernel.
+
+Sat Dec 25 20:00:47 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * configure.in: Nuke hacks which were used to get a special
+ version of GAS for HPPA configurations.
+
+Sun Dec 19 20:40:44 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * configure: If only ${target_alias} is given, use that
+ as the default for ${host_alias}.
+ * configure: Add missing back-slashes before nested quotes.
+
+Wed Dec 15 18:07:18 1993 david d `zoo' zuhn (zoo@andros.cygnus.com)
+
+ * Makefile.in (BASE_FLAGS_TO_PASS): add YACC=$(BISON)
+
+Tue Dec 14 21:25:33 1993 Per Bothner (bothner@cygnus.com)
+
+ * config.guess: Recognize some Tektronix configurations.
+ From Kaveh R. Ghazi <ghazi@noc.rutgers.edu>.
+
+Sat Dec 11 11:18:00 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config.sub: Match any flavor of SH.
+
+Thu Dec 2 17:16:58 1993 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * configure.in: Don't try to configure newlib for Alpha.
+
+Thu Dec 2 14:35:54 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in: Don't build ld for Irix 5. Don't build gas,
+ libg++ or libio for any Alpha target.
+
+ * configure.in (mips*-sgi-irix5*): New target; use mh-irix5.
+ * config/mh-irix5. New file for Irix 5.
+
+Wed Dec 1 17:00:33 1993 Jason Merrill (jason@deneb.cygnus.com)
+
+ * Makefile.in (GZIPPROG): Renamed from GZIP, which gzip uses for
+ default arguments -- so it tried to compress itself.
+
+Tue Nov 30 13:45:15 1993 david d `zoo' zuhn (zoo@andros.cygnus.com)
+
+ * configure.in (notsupp): ensure that a space is always at the end
+ of the configdirs list, since the grep checks for an explicit space
+
+Tue Nov 16 15:04:27 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in (target i386-sysv4.2): don't build ld, since static
+ versions of many libraries are not available.
+
+Tue Nov 16 14:28:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.guess: Recognize Apollos (using environment variables).
+ * configure.in: Don't configure ld, binutils, or gprof for Apollo.
+
+Thu Nov 11 12:03:50 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.guess: Recognize Sony news mips running newsos.
+
+Wed Nov 10 16:57:00 1993 Mark Eichin (eichin@cygnus.com)
+
+ * Makefile.in (all-cygnus, build-cygnus): "fi else" needs to be
+ "fi ; else" for bash.
+
+Tue Nov 9 15:54:01 1993 Mark Eichin (eichin@cygnus.com)
+
+ * Makefile.in (BASE_FLAGS_TO_PASS): pass SHELL.
+
+Fri Nov 5 08:07:27 1993 D. V. Henkel-Wallace (gumby@blues.cygnus.com)
+
+ * config.sub: accept unixware as an alias for svr4.2.
+ Fix some inconsistancies with the gcc version.
+
+Fri Nov 5 15:14:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (DISTDOCDIRS): Add gdb.
+
+Fri Nov 5 11:59:42 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * Makefile.in (DISTDOCDIRS): Add libg++ and libio.
+
+Fri Nov 5 10:35:05 1993 Ken Raeburn (raeburn@rover.cygnus.com)
+
+ * Makefile.in (taz): Only build "info" in DISTDOCDIRS.
+ (DISTDOCDIRS): Don't assume libg++ and gdb folks necessarily want
+ this now.
+
+Thu Nov 4 18:58:23 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.sub: Accept hiux* as an OS name.
+
+ * Makefile.in: Change RUNTEST_FLAGS back to RUNTESTFLAGS per
+ etc/make-stds.texi. The underscore came from gcc, and dje now
+ agrees that RUNTESTFLAGS is the correct name.
+
+Thu Nov 4 10:49:01 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * install.sh: Remove 'set -e'. It makes any conditionals
+ in the script useless.
+
+ * config.guess: Automatically recognize arm-acorn-riscix
+ Patch from Richard Earnshaw (rwe11@cl.cam.ac.uk).
+
+Thu Nov 04 08:08:04 1993 Jeffrey Wheat (cassidy@cygnus.com)
+
+ * Makefile.in: Change RUNTESTFLAGS to RUNTEST_FLAGS
+
+Wed Nov 3 22:09:46 1993 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * Makefile.in (DISTDOCDIRS): New variable.
+ (taz): Edit local Makefile.in sooner, instead of proto-toplev
+ Makefile.in later. Build "info" and "dvi" in DISTDOCDIRS.
+
+Wed Nov 3 21:31:52 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in (hppa target): check the source directory for the
+ pagas sub-directory
+
+Wed Nov 3 11:12:22 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config.sub: Allow -aout* and -elf*.
+
+Wed Nov 3 11:08:33 1993 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * configure.in: Don't build ld on i386-solaris2, same as for
+ sparc-solaris2.
+
+Tue Nov 2 14:21:25 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * Makefile.in (taz): Add texinfo/lgpl.texinfo (for libg++).
+
+Tue Nov 2 13:38:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * configure.in: Configure gdb for alpha.
+
+Mon Nov 1 10:42:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (CXXFLAGS): Add -O.
+
+Wed Oct 27 10:45:06 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * config.guess: added support for DG Aviion
+
+Tue Oct 26 14:37:37 1993 Ken Raeburn (raeburn@rover.cygnus.com)
+
+ * configure.in: Produce warning message for subdirectories not
+ configurable for this host/target combination. Don't try to
+ configure gdb for vms.
+
+Mon Oct 25 11:22:15 1993 Ken Raeburn (raeburn@rover.cygnus.com)
+
+ * Makefile.in (taz): Replace "byacc" with "bison -y" in the
+ appropriate files before making "diststuff".
+ (DISTBISONFILES): New var: list of files to be edited.
+ (DISTSTUFFDIRS): Add binutils.
+
+Fri Oct 22 20:32:15 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * config.sub: also handle mipsel and mips64el (for little endian mips)
+
+Fri Oct 22 07:59:20 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Add * to end of all OS names.
+
+Thu Oct 21 11:38:28 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * configure.in: Build newlib for LynxOS native.
+
+Wed Oct 20 09:56:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.guess: Add support for delta 88k running SVR3.
+
+ * configure.in: Add comment about HP compiler vs. emacs.
+
+Tue Oct 19 16:02:22 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: don't build ld on solaris2 (not a viable option
+ due to bugs in getpwnam & getpwuid)
+
+Tue Oct 19 15:13:56 1993 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * configure.in: Accept alpha-dec-osf1*, not just -osf1, since
+ config.guess will produce a full version number.
+
+Tue Oct 19 15:58:01 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in: Build linker and binutils for alpha-dec-osf1.
+
+Tue Oct 19 11:41:55 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Remove -O from CXXFLAGS for consistency with CFLAGS,
+ and gdb/testsuite/Makefile.in.
+
+Sat Oct 9 18:39:07 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: recognize mips*- instead of mips-
+
+Fri Oct 8 14:15:39 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * config.sub: Accept linux*coff and linux*elf as operating
+ systems.
+
+Thu Oct 7 12:57:19 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config.sub: Recognize mips64, and mips3 as an alias for it.
+
+Wed Oct 6 13:54:21 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * configure.in: Remove alpha-dec-osf*, no longer necessary now that
+ gdb knows how to handle OSF/1 shared libraries.
+
+Tue Oct 5 11:55:04 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Recognize hppa*-*-hiux* (currently synonym for hpux).
+ * config.guess: Recognize Hitachi's HIUX.
+ * config.sub: Recognize h3050r* and hppahitachi.
+ Remove redundant cases for hp9k[23]*.
+
+Mon Oct 4 16:15:09 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: default to '--with-gnu-as' and '--with-gnu-ld'
+ if gas and ld are in the source tree and are in ${configdirs}.
+ If ${use_gnu_as} or ${use_gnu_ld} are 'no', then don't set the
+ the --with options (but still pass them down on the command line,
+ if they were explicitly specified).
+
+Fri Sep 24 19:11:13 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure: substitute SHELL value in Makefile.in with
+ ${CONFIG_SHELL}
+
+Thu Sep 23 18:05:13 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in: Build gas, ld, and binutils for *-*-sysv4* and
+ *-*-solaris2* targets.
+
+Sun Sep 19 17:01:41 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * Makefile.in: define M4, and pass it down to sub-makes;
+ all-autoconf now depends on all-m4
+
+Sat Sep 18 00:38:23 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * Makefile.in ({AR,RANLIB}_FOR_TARGET): make contingent on
+ presence of {ar,ranlib} instead of a configured directory
+
+Wed Sep 15 08:41:44 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * config.guess: Accept 34?? as well as 33?? for NCR.
+
+Mon Sep 13 12:28:43 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: grab mt-hppa for HPPA targets; use 'gas ' instead
+ of 'gas' in sed commands, since 'gash' is now in the tree as well.
+
+Fri Sep 10 11:23:52 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure: grab values for $(CC) and $(CXX) from the
+ environment, so that someone can do "CC=gcc configure; make" and
+ have it work right (matching the way that autoconf works now)
+
+ * configure.in, Makefile.in: add support for gash, the tcl
+ interface to Galaxy
+
+ * config.guess: add NetBSD variants (hp300, x86)
+
+Thu Sep 9 16:48:52 1993 Jason Merrill (jason@deneb.cygnus.com)
+
+ * install.sh: Support -d option (in the manner of SunOS 4 install,
+ as it is more deterministic than that of GNU install)
+ (chmodcmd): Set file to mode 755 by default (should also do default
+ chgrp and chown, but I don't feel like dealing with that now)
+
+Tue Sep 7 11:59:39 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config.sub: Remove h8300hhms alias.
+
+Tue Aug 31 11:00:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Match *-*-solaris2* not *-sun-solaris2*.
+
+Mon Aug 30 18:29:10 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * Makefile.in (gcc-no-fixedincludes): touch stmp-fixproto as well
+ as stmp-fixinc
+
+Wed Aug 25 16:35:59 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config.sub: recognize m88110-bug-coff.
+
+Tue Aug 24 10:23:24 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * Makefile.in (all-libio): all dependencies on the toolchain used
+ to build this (gcc, gas, ld, etc)
+
+Fri Aug 20 17:24:24 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.guess: Deal with OSF/1 1.3 on alpha.
+
+Thu Aug 19 11:43:04 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * install.sh: add some 'else true' clauses for portability
+
+ * configure.in: don't build libio for h8[35]00-*-* targets
+
+Tue Aug 17 19:02:31 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * Makefile.in: Add support for new libio.
+
+Sun Aug 15 20:48:55 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * install.sh: If one command fails, don't try the rest. Don't try
+ to remove $dsttmp (via trap) unless we have already created it.
+ If $src doesn't exist, detect it and exit with an error.
+
+ * config.guess: Recognize BSD on hp300.
+
+Wed Aug 11 18:35:13 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * config.guess: Map (9000/[34]??:HP-UX:*:*) to m68k-hp-hpux.
+ Bug report from "Hamish (H.I.) Macdonald" <hamish@bnr.ca>.
+
+Wed Aug 11 15:37:51 1993 Jason Merrill (jason@deneb.cygnus.com)
+
+ * Makefile.in (all-send-pr): depends on all-prms
+
+Wed Aug 11 16:56:03 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.guess: Fix typo (9000/8??:4.3bsd -> 9000/7??:4.3bsd).
+
+Fri Aug 6 14:45:02 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config.guess: From michael@mercury.cs.mun.ca (Michael Rendell):
+ Added test for mips-mips-riscos5.
+
+Thu Aug 5 15:45:08 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: use mh-hp300 for 68k HP hosts
+
+Mon Aug 2 11:56:53 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure: add support for CONFIG_SHELL, so that you can use
+ some alternate shell for evaluating configure scripts
+
+Sun Aug 1 11:36:27 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (make-gdb.tar.gz): Sed bug reporting address
+ in configure script to bug-gdb@prep.ai.mit.edu when building
+ distribution archive.
+ * Makefile.in (COMPRESS): Remove def.
+ * Makefile.in (gdb.tar.gz, make-gdb.tar.gz): Renamed from
+ gdb.tar.Z and make-gdb.tar.Z respectively.
+ * Makefile.in (make-gdb.tar.gz): Now only build gzip'd archive.
+ * Makefile.in (make-gdb.tar.gz): Minor changes to move closer
+ to convergence with 'taz' target in Makefile.in.
+
+Fri Jul 30 12:34:57 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * install.sh (dsttmp): use trap to ensure that tmp files go
+ away on error conditions
+
+Wed Jul 28 11:57:36 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * Makefile.in (BASE_FLAGS_TO_PASS): remove LOADLIBES
+
+Tue Jul 27 12:43:40 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (install-dirs): Deal with a prefix like /gnu;
+ its parent is '/' not ''.
+
+ * Makefile.in (DEVO_SUPPORT): Add comments about ChangeLog.
+
+Fri Jul 23 09:53:37 1993 Jason Merrill (jason@wahini.cygnus.com)
+
+ * configure: if ${newsrcdir}/configure doesn't exist, don't assume
+ that ${newsrcdir}/configure.in does.
+
+Tue Jul 20 11:28:50 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * test-build.mk: support for CONFIG_SHELL
+
+Mon Jul 19 21:54:46 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * config.sub (netware): Add as a basic system type.
+
+Wed Jul 14 12:03:11 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in (Makefile): depend on configure.in. Also drop the
+ $(srcdir)/ from the dependency on Makefile.in.
+
+Tue Jul 13 20:10:58 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config.sub: Recognize h8300hhms as h8300h-hitachi-hms.
+ (h8300hhms is temporary until multi-libraries are implemented).
+ * configure.in: Handle h8300h too.
+
+Sun Jul 11 17:35:27 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.guess: Recognize dpx/2 as m68k-bull-sysv3.
+
+Thu Jul 8 18:26:12 1993 John Gilmore (gnu@cygnus.com)
+
+ * configure: Remove extraneous output when guessing host type.
+ * config.guess: Remove extraneous output when guessing using C
+ compiler rather than uname, or when guessing fails.
+
+Wed Jul 7 17:58:14 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com)
+
+ * Makefile.in: remove all.cross and install.cross targets
+
+ * configure: remove CROSS=-DCROSS_COMPILE and ALL=all.cross
+ definitions
+
+Tue Jul 6 10:39:44 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * configure.in (target sh): Build gprof.
+
+Thu Jul 1 16:52:56 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config.sub: change -solaris to -solaris2
+
+Thu Jul 1 15:46:16 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Use config/mh-riscos for mips-*-sysv*.
+
+Wed Jun 30 09:31:58 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure: Correct error message for missing Makefile.in to
+ print correct directory.
+
+Tue Jun 29 13:52:16 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * install.sh: kludge around 386BSD shell bug
+
+Tue Jun 29 13:06:49 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * config.guess: Recognize NeXT.
+ * config.guess: Recognize i486-ncr-sysv4.
+ * Makefile.in (taz): rm $(TOOL)-$$VER before linking.
+
+Tue Jun 29 12:50:57 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (MAKEINFOFLAGS): New variable.
+ (FLAGS_TO_PASS): Pass MAKEINFO as MAKEINFO MAKEINFOFLAGS.
+ * build-all.mk, test-build.mk: Pass down --no-split as
+ MAKEINFOFLAGS when hosted on DOS. Compile DOS hosted without -g.
+
+Thu Jun 24 13:39:11 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in (DEVO_SUPPORT): Add COPYING COPYING.LIB install.sh.
+
+Wed Jun 23 12:59:21 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in (libg++.tar.z): New rule.
+ * Makefile.in (taz): Replace 'configure -rm' by 'make distclean'.
+ * Makefile.in (taz): Only do a single chmod.
+
+Fri Jun 18 12:03:10 1993 david d `zoo' zuhn (zoo at majipoor.cygnus.com)
+
+ * install.sh: don't use dirname anymore (replaced with sed usage)
+
+Thu Jun 17 18:43:42 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in: Change extension for gzip'd files from '.z' to
+ '.gz' per new FSF standard usage.
+
+Thu Jun 17 16:58:50 1993 david d `zoo' zuhn (zoo at majipoor.cygnus.com)
+
+ * configure: put quotes around the final value of program_transform_name
+
+Tue Jun 15 16:48:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: new install.sh support; update install-info rules
+
+Wed Jun 9 12:31:34 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in: Build diff for crosses, but not for go32 host.
+
+ * configure.in: Build gprof only for native, and don't build it
+ for mips-*-*, rs6000-*-*, or i[34]86-*-sco*.
+
+Mon Jun 7 13:12:11 1993 david d `zoo' zuhn (zoo at deneb.cygnus.com)
+
+ * configure.in: don't build gas,ld,binutils on for *-*-sysv4
+
+Mon Jun 7 11:40:11 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * configure.in (host_tools): Add prms.
+
+Fri Jun 4 13:30:42 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: install gcc, do installation of $(INSTALL_MODULES)
+ with $(FLAGS_TO_PASS) on the command line
+
+ * config.sub: Recognize lynx and lynxos
+
+Fri Jun 4 10:59:56 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config.sub: Accept -ecoff*, not just -ecoff.
+
+Thu Jun 3 17:38:54 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (taz): Use .gz suffix instead of .z.
+ (binutils.tar.gz, gas+binutils.tar.gz, gas.tar.gz): Fixed target
+ names.
+
+Thu Jun 3 00:27:06 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in (vault-install): add an 'else true' (for Ultrix)
+
+Wed Jun 2 18:19:16 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in (install-no-fixedincludes): install gcc last, so
+ that rebuilds that might happen during 'make install' don't get
+ bogus gcc include files
+
+Wed Jun 2 16:14:10 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ Change from Utah for HPPA support:
+ * config.guess: Recognize hppa1.x-hp-bsd.
+
+Wed Jun 2 11:53:33 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * config.guess: Add support for Motorola Delta 68k, up to r3v7.
+ Patch from pot@fly.cnuce.cnr.it (Francesco Potorti`).
+
+Tue Jun 1 17:48:42 1993 Rob Savoye (rob at darkstar.cygnus.com)
+
+ * config.sub: Add support for rom68k and bug boot monitors.
+
+Mon May 31 09:36:37 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in: Make all-opcodes depend on all-bfd.
+
+Thu May 27 08:05:31 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config.guess: Added special check for i[34]86-univel-sysv4*.
+
+Wed May 26 16:33:40 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config.guess: For i[34]86-unknown-sysv4 use UNAME_MACHINE for
+ the processor rather than assuming i486.
+
+Wed May 26 09:40:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.guess: Recognize SunOS6 as Solaris3.
+
+Tue May 25 23:03:11 1993 Per Bothner (bothner@cygnus.com)
+
+ * config.guess: Fix typo. Avoid #elif (not in K&R 1).
+ Recognize SunOS 5.* only (and not [6-9].*) as being Solaris2.
+
+Tue May 25 12:44:18 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * build-all.mk (all-cross): New target for Canadian Cross.
+ Added Q2 go32 targets.
+ * test-build.mk: Configure go32 cross sparclite-aout and
+ mips-idt-ecoff -with-gnu-ld. Moved build binary directory from
+ PARTIAL_HOLE_DIRS to BUILD_HOLES_DIRS.
+
+Mon May 24 15:30:06 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: fix Alpha GDB typo; also, don't build DejaGnu for
+ GO32 hosted toolchains
+
+Mon May 24 14:18:41 1993 Rob Savoye (rob at darkstar.cygnus.com)
+
+ * configure: change so "-exec-prefix" gets passed down rather
+ than "-exec_prefix" so autoconf generated Makefiles get the
+ exec_prefix set right.
+
+Fri May 21 10:42:25 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config.guess: get the Solaris2 minor version number
+
+ * Makefile.in: add standards.texi and make-stds.texi to ETC_SUPPORT
+
+Fri May 21 06:20:52 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * config.guess: Recognize some Sequent platforms.
+
+Thu May 20 14:33:48 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: added the vault-install target
+
+ * configure.in: actually use the Sun3 makefile fragment that's in
+ config, also added the release dir to configdirs
+
+Thu May 20 14:19:18 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (taz): Fix modes on stuff in $(TOOL) dir also.
+
+Tue May 18 20:26:41 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: remove some program from Alpha targetted toolchains
+
+Tue May 18 15:23:19 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * Makefile.in (DISTSTUFFDIRS): Renamed from PROTODIRS. Add ld and
+ gprof.
+ (taz): Run "make diststuff" in those directories instead of "make
+ proto-dir". Look for "VERSION=" only at start of line in subdir
+ Makefile. Use "gzip -9" for compression.
+ (TEXINFO_SUPPORT, DIST_SUPPORT, BINUTILS_SUPPORT_DIRS): New vars.
+ (binutils.tar.z): New target.
+
+Mon May 17 17:01:15 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * Makefile.in (taz): Include gpl.texinfo.
+
+Fri May 14 06:48:38 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * Makefile.in (setup-dirs): Merged into "taz" target.
+ (taz): Only do `proto-dir' stuff if a directory is actually needed
+ for this target.
+
+Wed May 12 13:09:44 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (MUNCH_NM): New variable, defined to be $(NM).
+ (FLAGS_TO_PASS): Pass down MUNCH_NM.
+ (HOST_CC, HOST_PREFIX, HOST_PREFIX_1): New variables.
+ (EXTRA_GCC_FLAGS): Pass down HOST_* variables.
+ (gcc-no-fixedincludes): Correct for current gcc Makefile.
+
+Tue May 11 10:14:25 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (make-gdb.tar.Z): Add configure, config.guess,
+ config.sub, and move-if-change to gdb testsuite distribution
+ archive, so the testsuite can be extracted, configured, and
+ run separately from the gdb distribution. Blow away the Chill
+ tests that require a Chill compiled executable, since GNU Chill
+ is not yet publically available.
+
+Mon May 10 17:22:26 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * test-build.mk: set environment variables in a single command,
+ instead of a list of assignments and exports
+
+ * config.guess: recognize Alpha/OSF1 systems
+
+Mon May 10 14:55:51 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * configure: Change help message to prefer --options rather than
+ -options.
+
+Mon May 10 05:58:35 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * config.sub: Convergent Tech. "miniframe" uses m68010, sez
+ zippy@ecst.csuchico.edu.
+ * config.guess: Recognize miniframe.
+
+Sun May 9 17:47:57 1993 Rob Savoye (rob at darkstar.cygnus.com)
+
+ * Makefile.in: Use srcroot to find runtest rather than rootme.
+ Pass RUNTESTFLAGS and EXPECT down in BASE_FLAGS_TO_PASS.
+
+Fri May 7 14:55:59 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * test-build.mk: Extensive additions to support building on a
+ machine other than the host.
+
+Wed May 5 08:35:04 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * configure (tooldir): Fix for i386-aix again.
+
+Mon May 3 19:00:27 1993 Per Bothner (bothner@cygnus.com)
+
+ * configure, Makefile.in: Change definition of $(tooldir)
+ to match the FSF.
+
+Fri Apr 30 15:55:21 1993 Fred Fish (fnf@cygnus.com)
+
+ * config.guess: Recognize i[34]86/SVR4.
+
+Fri Apr 30 15:52:46 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * Makefile.in (all-gdb): gdb depends on sim.
+
+Thu Apr 29 23:30:48 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (gdb.tar.Z): Make prototype gdb testsuite directory
+ at the same time we make the prototype gdb directory.
+ * Makefile.in (make-gdb.tar.Z): Make the testsuite distribution
+ files at the same time as the gdb base release distribution.
+
+Thu Apr 29 12:50:37 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (check): Use individual check targets rather than
+ DO_X rule.
+ (check-gcc): Added.
+
+Thu Apr 29 09:50:07 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config.sub: Use sysv3.2 not sysv32 for canonical OS
+ for System V release 3.2.
+
+Thu Apr 29 10:33:22 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config.sub: Recognize hppaosf.
+ * configure.in: Do configure ld/binutils/gas for it.
+
+Tue Apr 27 06:25:34 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * configure (tooldir): Alter syntax used to set this, for systems
+ where "\$" isn't handled right, like i386-aix.
+
+Thu Apr 22 08:17:35 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure: Pass program-transform-name, not
+ program_transform_name, to recursive configures.
+
+Thu Apr 22 02:58:21 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * Makefile.in (gas+binutils.tar.z): New rule for building snapshots
+ of gas+ld+binutils.
+
+Mon Apr 19 17:41:30 1993 Per Bothner (bothner@cygnus.com)
+
+ * config.guess: Recognize AIX3.2 as distinct from 3.1.
+
+Sat Apr 17 17:19:50 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: rename m88k-motorola-m88kbcs to m88k-motorola-sysv
+
+ * config/mh-delta88: remove extraneous GCC references
+
+Tue Apr 13 16:52:16 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * Makefile.in (PRMS): Set back to all-prms.
+
+Sat Apr 10 12:04:07 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * test-build.mk: Pass -with-gnu-as for known MIPS native and MIPS
+ targets, rather than for MIPS hosts.
+
+Fri Apr 9 13:51:06 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: add comment for --with-x default values
+
+ * config.guess: handle Motorola Delta88 box for SVR3 and SVR4.
+
+ * Makefile.in: add check-* targets for each of the directories in
+ the tree. Add a definition of RUNTEST that will use the one we
+ just built, if it exists. Pass this down via FLAGS_TO_PASS.
+
+Thu Apr 8 09:21:30 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in: Removed obsolete references to bfd_target and
+ target_makefile_frag.
+
+ * build-all.mk: Set assorted targets for Q2.
+ * config.sub: Recognize z8k-sim and h8300-hms.
+ * test-build.mk: Really don't pass host to configure.
+ (HOLES): Added uname.
+
+Wed Apr 7 15:48:19 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure: Handle an empty program-prefix, program-suffix or
+ program-transform-name correctly.
+
+Tue Apr 6 13:48:41 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * build-all.mk: -G 8 no longer required for MIPS targets.
+ * test-build.mk: Don't pass host argument to configure; make it
+ guess.
+
+Tue Apr 6 10:36:53 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (gdb.tar.Z): Fix for building gzip'd distribution.
+ * Makefile.in (COMPRESS): New macro, like GZIP.
+
+Fri Apr 2 09:02:31 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * test-build.mk: Use -with-gnu-as for mips-sgi-irix4 as well.
+
+ * build-all.mk: Set GCC to gcc -O -G 8 for MIPS targets, since gcc
+ with gas currently defaults to -G 0.
+
+Thu Apr 1 08:25:42 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (all-flex): flex depends on byacc.
+
+ * build-all.mk: If host not specified, use config.guess. Pass TAG
+ to test-build.mk as RELEASE_TAG.
+ * test-build.mk (configargs): New variable containing arguments to
+ pass to configure. Set to -with-gnu-as on mips-dec-ultrix.
+ (FLAGS_TO_PASS): Pass down RELEASE_TAG.
+
+ * config.guess: Use /bin/uname when checking -X argument on SCO,
+ to avoid invoking GNU uname which doesn't understand -X.
+
+ * test-build.mk: Don't use /usr/unsupported/bin/as on AIX.
+
+ * configure.in: Build gas for mips-*-*.
+
+Wed Mar 31 21:20:58 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in (all.normal): insert missing backslash.
+
+Wed Mar 31 12:31:56 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * build-all.mk, config/mh-irix4: Bump -XNh value to 1500 to match
+ gcc requirements.
+
+ * Makefile.in: Complete overhaul to merge many almost identical
+ targets.
+
+Tue Mar 30 20:17:01 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (setup-dirs-gdb): Renamed from setup-dirs.
+ (gdb.tar.Z): Adjusted.
+
+ * Makefile.in (setup-dirs, taz): New targets; should be general
+ enough to adapt for gdb sometime. Build only .z file.
+ (gas.tar.z): New target.
+
+Tue Mar 30 10:03:09 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * build-all.mk: Use CC=cc -Xs on Solaris.
+
+Mon Mar 29 19:59:26 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config/mh-sun3: cc needs -J to compile cp-parse.c correctly
+
+ * config/mh-solaris: SunPRO C needs -Xs to be able to get a
+ working xmakefile for Emacs.
+
+Thu Mar 25 15:14:30 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in: Incorporate changes suggested by wilson@cygnus.com
+ for handling BISON for FSF releases.
+
+Thu Mar 25 06:19:48 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * configure: Actually implement the change zoo just documented.
+
+Wed Mar 24 13:02:44 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com)
+
+ * configure: when using config.guess, only set target_alias when
+ it's not already been set (ie, on the command line)
+
+Mon Mar 22 23:07:39 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: add installcheck target, set PRMS to install-prms
+
+Sun Mar 21 16:46:12 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure: add support for package_makefile_fragment, handle the
+ case where a directory has a configure.in file but no Makefile.in
+ more gracefully (with an actual understandable error message, even);
+ add support for --without (and add this to the usage message); also
+ explicitly add a --host=${host_alias} to the command line when
+ config.guess is used
+
+Sun Mar 21 12:11:58 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * configure: Must use both --host and --target in recursive calls.
+
+Thu Mar 18 12:31:35 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: Change deja-gnu to dejagnu.
+
+Mon Mar 15 15:44:35 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in (h8300-*-*, h8500-*-*): Don't build libg++.
+
+Fri Mar 12 18:30:14 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: canonicalize all instances to *-*-solaris2*,
+ also strip out a number of tools to not build for go32 host
+
+Wed Mar 10 12:08:27 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * config.guess: add GPL.
+
+ * Makefile.in, config.guess, config.sub, configure: bump
+ copyrights to 93.
+
+Wed Mar 10 07:12:48 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (do-info): Removed obsolete check for existence of
+ localenv file.
+
+ * Makefile.in (MAKEOVERRIDES): Define to be empty.
+
+Wed Mar 10 03:11:56 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: a couple of 'else true' for decstation,
+ support for TclX
+
+ * configure.in: configure tclX too; don't remove Tk on RS/6000 anymore
+
+Tue Mar 9 16:06:12 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in (setup-dirs): change invocation of make to $(MAKE).
+
+Mon Mar 8 14:52:11 1993 Ken Raeburn (raeburn@cambridge)
+
+ * config.guess: Recognize i386-ibm-aix (PS/2).
+ * configure.in: Use config/mh-aix386 file for it.
+
+Mon Mar 8 11:12:43 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (GCC_FOR_TARGET): Eliminated definition; use
+ CC_FOR_TARGET instead.
+ (BASE_FLAGS_TO_PASS): Pass GCC_FOR_TARGET=$(CC_FOR_TARGET).
+
+Wed Mar 3 16:00:28 1993 Steve Chamberlain (sac@ok.cygnus.com)
+
+ * Makefile.in: Add sim to list of directories sent with gdb
+
+Wed Mar 3 11:42:39 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * configure.in: Put back mips-dec-bsd* case.
+
+Tue Mar 2 21:15:58 1993 Fred Fish (fnf@cygnus.com)
+
+ (Ultrix 2.2 support from Michael Rendell <michael@mercury.cs.mun.ca>)
+ * configure.in (vax-*-ultrix2*): Add Ultrix 2.2 triplet.
+ * config.guess: Change 'VAX*:ULTRIX:*:*' to 'VAX*:ULTRIX*:*:*'.
+ * config/mh-vaxult2: New file.
+
+Tue Mar 2 18:11:03 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: remove no-op mips-dec-bsd* in "case $target"
+
+ * Makefile.in (dir.info): only run gen-info-dir if it exists,
+ (install-info): install dir.info only if it exists,
+ (all-expect, install-expect): pass along X11_FLAGS_TO_PASS
+
+Tue Mar 2 09:01:30 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * configure.in: For vms target, skip bfd, ld, binutils. Do build
+ gas for mips-dec-bsd.
+
+Tue Mar 2 08:35:24 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure (makesrcdir): If ${srcdir} is relative and not ".",
+ and ${subdir} is not ".", set makesrcdir based on ${invsubdir}.
+
+Tue Feb 23 14:18:28 1993 Mike Werner (mtw@poseidon.cygnus.com)
+
+ * configure.in: Added "dejagnu" to hosttools list.
+
+Mon Feb 22 23:28:38 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * config.sub, configure.in, config.guess: Add support
+ for Bosx, an AIX variant from Bull.
+ Patches from F.Pierresteguy@frcl.bull.fr.
+
+Sun Feb 21 11:15:22 1993 Mike Werner (mtw@poseidon.cygnus.com)
+
+ * devo/dejagnu: Initial creation of devo/dejagnu.
+ Migrated dejagnu testcases and support files for testing software
+ tools to reside as subdirectories, currently called "testsuite",
+ within the directory of the software tool. Migrated all programs,
+ support libraries, etc. beloging to dejagnu proper from
+ devo/deja-gnu to devo/dejagnu. These files were moved "as is"
+ with no modifications. The changes to these files which will
+ allow them to configure, build, and execute properly will be made
+ in a future update.
+
+Fri Feb 19 20:19:39 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * Makefile.in: Change send_pr to send-pr.
+ * configure.in: Likewise.
+ * send_pr: Renamed directory to send-pr.
+
+Fri Feb 19 19:00:13 1993 Per Bothner (bothner@cygnus.com)
+
+ * Makefile.in: Add some extra semi-colons (needed if SHELL=bash).
+
+Fri Feb 19 00:59:33 1993 John Gilmore (gnu@cygnus.com)
+
+ * README: Update for gdb-4.8 release.
+ * Makefile.in (gdb.tar.Z): Add texinfo/tex3patch. Build
+ gdb-xxx.tar.z (gzip'd) file also.
+
+Thu Feb 18 09:16:17 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: make all-diff depend on all-libiberty
+
+Tue Feb 16 16:06:31 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * config.guess: add vax-ultrix in the spirit of mips-ultrix.
+
+Tue Feb 16 05:57:15 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in, Makefile.in: add hello, tar, gzip, recode, indent
+
+Tue Feb 16 00:58:20 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (DEVO_SUPPORT): Remove etc directory
+ (ETC_SUPPORT): Only add the files GDB wants from etc/.
+ (gdb.tar.Z): Use ETC_SUPPORT. Use byacc when building the file.
+
+Thu Feb 11 20:14:28 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: makeinfo binary is in a new location
+
+Tue Feb 9 12:42:27 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config.sub: Accept -ecoff as an OS.
+
+ * Makefile.in: Various changes to eliminate a level of make
+ recursion and reduce the required command line length.
+ (BASE_FLAGS_TO_PASS): New variable holding flags passed to all
+ sub-makes.
+ (EXTRA_HOST_FLAGS, EXTRA_TARGET_FLAGS, EXTRA_GCC_FLAGS): New
+ variables holding settings for specific sub-makes.
+ (FLAGS_TO_PASS, TARGET_FLAGS_TO_PASS, GCC_FLAGS_TO_PASS): Rewrote
+ in terms of BASE_FLAGS_TO_PASS.
+ (TARGET_LIBS): New variable listing directories which use
+ TARGET_FLAGS_TO_PASS.
+ (subdir_do): Eliminated.
+ (do-*): New set of targets to replace subdir_do.
+ (various): All targets which used subdir_do now depend on do-*.
+ (local-clean): Renamed from do_clean.
+ (local-distclean): New target, dependency of distclean and
+ realclean.
+ (install-info): Don't create directories. Depend on dir.info
+ rather than calling make recursively.
+ (install-dir.info): Eliminated.
+ (install-info-dirs): Create all info directories here.
+ (dir.info): Depend upon do-install-info.
+
+ * test-build.mk (HOLES): Added false.
+
+Sat Feb 6 14:05:09 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * config.guess: Recognize BSDI and BSDJ (Jolitz 386bsd).
+
+Thu Feb 4 20:49:18 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in (info): remove dependency on all-texinfo. The
+ problem was really in texinfo/C, not at this level.
+
+Thu Feb 4 13:38:41 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (info): Added dependency on all-texinfo (PR 2112).
+
+Thu Feb 4 01:50:53 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (make-gdb.tar.Z): Change BISON to 'bison -y' for
+ GDB releases.
+
+Wed Feb 3 17:22:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * configure: Include srcdir in message about target of link not
+ being found. Don't convert `-' to `_' in `with' options being
+ passed to subdirs.
+
+Tue Feb 2 18:57:59 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: add uudecode to host_tools
+
+ * Makefile.in: added {all,install}-uudecode targets, added them to
+ the appropriate lists
+
+Tue Feb 2 11:45:53 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (all-gcc): Added dependency on all-gas.
+
+ * configure.in (mips-*-*): Build ld and binutils.
+
+Mon Feb 1 12:35:41 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * configure: check return code from mkdir, print error message and
+ exit on failure.
+
+Sat Jan 30 16:40:28 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (make-gdb.tar.Z): New location for texinfo.tex.
+
+Thu Jan 28 15:09:59 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * test-build.mk (HOLES): Added tar, cpio and uudecode.
+
+Wed Jan 27 16:50:32 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * config.sub (h8500): Recognize this as a cpu type.
+
+Sat Jan 23 20:32:01 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure: source directory missing is no longer a warning
+
+ * configure.in: recognize irix[34]* instead of irix[34]
+
+ * Makefile.in: define and pass down X11_LIB
+
+ * config/mh-sco: define X11_LIB to the mess that SCO ODT requires
+
+Sat Jan 23 13:49:40 1993 Per Bothner (bothner@cygnus.com)
+
+ * guess-systype: Renamed to ...
+ * config.guess: ... by popular request.
+ * configure.in, Makefile.in: Update accordingly.
+
+Thu Jan 21 12:20:55 1993 Per Bothner (bothner@cygnus.com)
+
+ * guess-systype: Patches from John Eaton <jwe@che.utexas.edu>:
+ + Add Convex, Cray/Unicos, and Encore/Multimax support.
+ + Execute ./dummy instead of assuming . is in PATH.
+
+Tue Jan 19 17:18:06 1993 Per Bothner (bothner@cygnus.com)
+
+ * guess-systype: New shell script. Attempts to guess the
+ canonical host name of the executing host.
+ Only a few hosts are supported so far.
+ * configure: Call guess-systype if no host is specified.
+
+Tue Jan 19 08:26:07 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (gcc-no-fixedincludes): Made to work with current
+ gcc Makefile.
+
+
+Fri Jan 15 10:27:02 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (GCC_FLAGS_TO_PASS): New variable.
+ (all-gcc, install-gcc, subdir_do): Use it.
+
+Wed Jan 13 17:06:45 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * Makefile.in: Rename uninstalled gcc driver from gcc to xgcc.
+
+Wed Jan 6 20:29:16 1993 Mike Werner (mtw@rtl.cygnus.com)
+
+ * Makefile.in: Removed explicit setting of SUBDIRS. SUBDIRS is now
+ set exclusively by configure, using configure.in .
+
+Wed Jan 6 13:44:11 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * test-build.mk: set $PATH for all builds
+
+ * Makefile.in: pass TARGET_FLAGS_TO_PASS for xiberty and libm
+
+Wed Jan 6 11:02:10 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (GCC_FOR_TARGET): Supply a default that matches
+ the one used in gcc/Makefile.in, so that a null expansion doesn't
+ override the one needed to build gcc with a native cc.
+
+
+Tue Jan 5 07:55:12 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * configure: Accept -with arguments.
+
+Sun Jan 3 15:15:09 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * Makefile.in: added h8300sim
+
+Tue Dec 29 15:06:00 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/mh-sco: Don't override BISON definition.
+
+ * build-all.mk: If canonhost is i386-unknown-sco3.2v4, change it
+ to i386-sco3.2v4. Set TARGETS and CFLAGS for i386-sco3.2v4.
+ (all-cygnus, native, build-cygnus): Make
+ $(canonhost)-stamp-3stage-done, not $(host)....
+ * test-build.mk (stamp-3stage-compared): Use tail +10c for
+ i386-sco3.2v4. Added else true to if command.
+
+Mon Dec 28 12:08:56 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * config.sub: (from FSF) Sequent uses a BSD-like OS.
+
+Mon Dec 28 08:32:06 1992 Minh Tran-Le (mtranle@paris.intellicorp.com)
+
+ * configure.in (i[34]86-*-isc*): added; uses mh-sysv.
+
+Thu Dec 24 17:26:24 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: don't remove binutils from Solaris builds
+
+Thu Dec 24 14:08:38 1992 david d`zoo' zuhn (zoo@cygnus.com)
+
+ * Makefile.in: get rid of earlier definitions for *clean,
+ also handle the recursive info rule better
+
+Thu Dec 24 12:40:21 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in (mostlyclean, distclean, realclean): Fix to
+ do more-or-less the right thing.
+
+Wed Dec 16 10:25:31 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: Add lines defining CC and CXX, and use CXX rather
+ than gcc in definitions of CXX_FOR_BUILD and CXX_FOR_TARGET.
+
+Tue Dec 15 00:34:32 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: change all $(host_cpu)-$(host_vendor)-$(host_os) to
+ $(host_canonical).
+
+ * configure.in: split the configdirs list into 4 categories (native
+ v. cross, library v. tool) and handle the cross-only and native-
+ only in more reasonable (and correct!) way.
+
+Mon Dec 14 17:04:22 1992 Stu Grossman (grossman at cygnus.com)
+
+ * configure.in (hppa*-*-*): Don't remove bfd and gdb from
+ configdirs anymore.
+
+Sun Dec 13 00:37:26 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: extensive cleanup:: removed all of the explicit
+ clean-* targets, collapsed many wrappers around subdir_do into
+ one, added additional targets to satisfy standards.texi, deleted
+ some old targets, some changes for consistency
+
+Fri Dec 11 20:18:02 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: handle some programs as cross-only, and others as
+ native only
+
+ * test-build.mk: handle partial holes in a more generic manner
+
+ * Makefile.in: m4 depends on libiberty
+
+Mon Dec 7 06:43:27 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config/mh-sco: don't default $(CC) to gcc
+
+Thu Dec 3 21:52:11 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: add m4, textutils, fileutils, sed, shellutils,
+ time, wdiff, and find to configdirs
+
+ * Makefile.in: all, clean, and install rules for the new programs
+ added to configure.in
+
+Mon Nov 30 14:54:34 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: use mh-sun for all *-sun-* hosts
+
+ * config/mh-solaris: rework standard X location to use
+ $OPENWINHOME, if defined.
+
+ * config/mh-sun: handle X11 include locations
+
+ * config/mh-decstation: define NeedFunctionPrototypes to 0, to
+ work around dain-bramaged DECwindows include files
+
+Fri Nov 27 18:35:54 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: define flags for X11 include files and library file
+ locations, pass them down to the programs that need this info
+
+ * build-all.mk: added a 'native' target, to 3stage the native toolchain
+
+ * config/{mh-hpux,mh-solaris}: define the "standard" locations for
+ the vendor supplied X11 headers and libraries
+
+Sun Nov 22 18:59:13 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: start building libg++ for HP-UX targets
+
+Wed Nov 18 19:33:11 1992 John Gilmore (gnu@cygnus.com)
+
+ * README: Update references to files moved into etc/.
+
+Sun Nov 15 09:36:08 1992 Fred Fish (fnf@cygnus.com)
+
+ * config.sub (i386sol2, i486sol2): i[34]86-unknown-solaris2.
+ * configure.in (i[34]86-*-solaris2*): Use config/mh-sysv4.
+
+Thu Nov 12 08:50:42 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure: accept dash as well as underscore in long option
+ names for FSF compatibility.
+
+Wed Nov 11 08:04:37 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * config.sub: added -sco3.2v4 support from FSF.
+
+Sun Nov 8 21:14:30 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: expand the section that adds or removes
+ directories from the list of programs to build, to handle native
+ vs. cross in addition to host v. native
+
+Sat Nov 7 18:52:27 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in: Replace C++ in macro names with CXX.
+ This is less likely to break ...
+
+Sat Nov 7 15:16:58 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * test-build.mk: add -w to GNU_MAKE
+
+Fri Nov 6 23:10:37 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config.sub: remove 'sparc'-->'sparc-sun' default transformation,
+ add 'sparc' to list of recognized cpus. This needed to make
+ 'sparc-aout' expand to 'sparc-unknown-aout' instead of 'sparc-sun-aout'.
+ Delete some redundant ose68 variants. Recognize -wrs as an os,
+ then changes that into $CPU-wrs-vxworks.
+
+ * configure.in: remove most references to gdbtest, regularize
+ target based program removal
+
+ * test-build.mk: import from p3 tree (many fixes and changes)
+
+Fri Nov 6 20:59:00 1992 david d `zoo' zuhn (zoo@cygnus.com)
+
+ * Makefile.in: added rules to handle tcl, tk, and expect
+
+ * configure.in: handle those directories if they exist
+
+Thu Nov 5 14:35:41 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config.sub: removed bogus hppabsd and hppahpux names, since
+ "hppa" is not a valid cpu (hppa1.1 or hppa1.0 are, though)
+
+Thu Oct 29 00:12:41 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: all-gcc now depends on all-binutils. all-libg++
+ depends upon all-xiberty
+
+ * Makefile.in: changes from p3, including:
+
+ Thu Oct 8 15:00:17 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (XTRAFLAGS): include newlib directories if
+ newlib/Makefile exists, rather than if host != target.
+
+ Fri Sep 25 13:41:52 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: added -nostdinc to XTRAFLAGS if we are using gcc
+ from the same source tree and not building a cross-compiler. This
+ matters for the libg++ configuration if reconfiguring a tree that
+ has already been installed.
+
+ Thu Sep 10 10:35:51 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: added -I for newlib/targ-include to XTRAFLAGS, to
+ pick up the machine and system specific header files.
+
+ * Makefile.in: added AS_FOR_TARGET, passed down in
+ TARGET_FLAGS_TO_PASS. Added CC_FOR_BUILD, which is intended to be
+ the C compiler to use to create programs which are run in the
+ build environment, set it to default to $(CC), and passed it down
+ in FLAGS_TO_PASS and TARGET_FLAGS_TO_PASS.
+
+ Mon Sep 7 22:34:42 1992 Ian Lance Taylor (ian@cirdan.cygnus.com)
+
+ * Makefile.in: add $(host) = $(target) tests back to *_FOR_TARGET.
+ We need them for unusual native builds, like systems without
+ ranlib.
+
+ * configure: also define $(host_canonical) and
+ $(target_canonical), which are the full, canonical names for the
+ given host and target
+
+Sun Nov 1 16:38:17 1992 Per Bothner (bothner@cygnus.com)
+
+ * Makefile.in: Added separate definitions for C++.
+
+Fri Oct 30 11:37:52 1992 Fred Fish (fnf@cygnus.com)
+
+ * configure.in (configdirs): Add deja-gnu.
+
+Fri Oct 23 00:39:18 1992 John Gilmore (gnu@cygnus.com)
+
+ * README: Update for configure.texi and gdb-4.7 release.
+
+Wed Oct 21 21:54:27 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in: Move "all" target to top of file.
+ Previously, first target was ".PHONY" which caused BSD4.4 make
+ to build .PHONY when make was run without arguments.
+
+Mon Oct 19 01:17:54 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in: Add COPYING.LIB to GDB releases, now that there's
+ Library-copylefted code in libiberty.
+
+Tue Oct 13 01:22:32 1992 John Gilmore (gnu@cygnus.com)
+
+ * config.sub: Replace m68kmote with plain old m68k.
+
+Fri Oct 9 03:14:24 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in: Remove space from blank line, avoid Make complaints.
+
+Thu Oct 8 18:41:45 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * config.sub: Complain if no argument is given. Added support for
+ 386bsd as OS and target alias.
+
+Thu Oct 8 15:07:22 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (XTRAFLAGS): include newlib directories if
+ newlib/Makefile exists, rather than if host != target.
+
+Mon Oct 5 03:00:09 1992 Mark Eichin (eichin at tweedledumber.cygnus.com)
+
+ * config.sub: recognize sparclite-wrs-vxworks.
+
+ * Makefile.in (install-xiberty): added *-xiberty make rules (from
+ p3.) Added clean-xiberty to clean.
+
+Thu Oct 1 17:59:19 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: use *-*-* instead of nested cases for host and target
+
+Tue Sep 29 14:11:18 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: added -nostdinc to XTRAFLAGS if we are using gcc
+ from the same source tree and not building a cross-compiler. This
+ matters for the libg++ configuration if reconfiguring a tree that
+ has already been installed.
+
+Sep 20 08:53:10 1992 Fred Fish (fnf@cygnus.com)
+
+ * config.sub (i486v/i486v4): Merge in from FSF version.
+
+Fri Sep 18 00:32:00 1992 Mark Eichin (eichin@cygnus.com)
+
+ * configure: only set PWD if it is already set.
+
+Thu Sep 17 23:05:53 1992 Mark Eichin (eichin@cygnus.com)
+
+ * configure: just set PWD=`pwd` at the top, since Ultrix sh
+ doesn't have unset and all success paths (and most error paths)
+ out set it anyway. (Note: should change all uses of ${PWD=`pwd`}
+ to just ${PWD} to avoid confusion.)
+
+Tue Sep 15 16:00:54 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure: always set $(tooldir) to $(libdir)/$(target_alias),
+ even for a native compilation.
+
+Tue Sep 15 02:22:56 1992 John Gilmore (gnu@cygnus.com)
+
+ Changes to make the gdb.tar.Z rule work better.
+
+ * Makefile.in (GDB_SUPPORT_DIRS): Add opcodes.
+ (DEVO_SUPPORT): Add configure.texi.
+ (bfd-ilrt.tar.Z): Remove ancient rule.
+
+Thu Sep 10 10:43:19 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: added -I for newlib/targ-include to XTRAFLAGS, to
+ pick up the machine and system specific header files.
+
+ * configure.in, config.sub: added new target m68010-adobe-scout,
+ with alias of adobe68k. Changed configure.in to check for
+ -scout before -sco* to avoid a false match.
+
+ * Makefile.in: added AS_FOR_TARGET, passed down in
+ TARGET_FLAGS_TO_PASS. Added CC_FOR_BUILD, which is intended to be
+ the C compiler to use to create programs which are run in the
+ build environment, set it to default to $(CC), and passed it down
+ in FLAGS_TO_PASS and TARGET_FLAGS_TO_PASS.
+
+Wed Sep 9 12:21:42 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: added TARGET_FLAGS_TO_PASS, CC_FOR_TARGET,
+ AR_FOR_TARGET, RANLIB_FOR_TARGET, NM_FOR_TARGET. Pass
+ TARGET_FLAGS_TO_PASS, which defines CC, AR, RANLIB and NM as the
+ FOR_TARGET variants, to newlib and libg++.
+
+Tue Sep 8 17:28:30 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (all-gas, all-gdb): Require all-opcodes to be built
+ first.
+
+Wed Sep 2 02:50:05 1992 John Gilmore (gnu@cygnus.com)
+
+ * config.sub: Accept `elf' as an environment.
+
+Tue Sep 1 15:48:30 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * Makefile.in (all-opcodes): cd into the right directory
+
+Sun Aug 30 21:12:11 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure: added -program_transform_name option, used as
+ argument to sed when installing programs.
+ configure.texi: added documentation for -program_prefix,
+ -program_suffix and -program_transform_name.
+
+Thu Aug 27 21:59:44 1992 John Gilmore (gnu@cygnus.com)
+
+ * config.sub: Accept i486 where i386 ok.
+
+Thu Aug 27 13:04:42 1992 Brendan Kehoe (brendan@rtl.cygnus.com)
+
+ * config.sub: accept we32k
+
+Mon Aug 24 14:05:14 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * config.sub, configure.in: accept OSE68000 and OSE68k.
+
+ * Makefile.in: don't create all directories for ``make install'';
+ let the subdirectories create the ones they need.
+
+Tue Aug 11 23:13:17 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * COPYING: new file, GPL v2
+
+Tue Aug 4 01:12:43 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: use the new gen-info-dir, which needs a template
+ argument (which also lives in texinfo)
+
+ * configure.texi, standards.texi: fix INFO-DIR-ENTRY
+
+Mon Aug 3 15:41:28 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config/mh-solaris: removed the -xs from CFLAGS (let the people
+ with Sun's C compiler deal with it themselved)
+
+Mon Aug 3 00:34:17 1992 Fred Fish (fnf@cygnus.com)
+
+ * config.sub (ncr3000): Change i386 to i486.
+
+Thu Jul 23 00:12:17 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: add install-rcs, install-grep to
+ install-no-fixedincludes, removed install-bison and install-libgcc
+
+Tue Jul 21 01:01:50 1992 david d `zoo' zuhn (zoo@cygnus.com)
+
+ * configure.in: grab the HPUX makefile fragment if on HPUX
+
+Mon Jul 20 11:02:09 1992 D. V. Henkel-Wallace (gumby@cygnus.com)
+
+ * Makefile.in: eradicate bison spoor (ditto libgcc).
+ configure.in: recognise m68{k,000}-ericsson-OSE.
+ es1800 is alias for m68k-ericsson-OSE
+
+Sun Jul 19 17:49:02 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: rearrange the parts that remove programs from
+ configdirs, based now on HOST==TARGET or by canonical triple.
+
+Fri Jul 17 22:52:49 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * test-build.mk: recurse explicitly with -f test-build.mk when
+ appropriate. predicate stage3 and comparison on the existence
+ of gcc. That is, if gcc isn't around, we aren't three-staging.
+ On very clean, also remove ...stamp-co. Build in-place before
+ doing other builds.
+
+Thu Jul 16 18:33:09 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * Makefile.in, configure.in: add tgas
+
+Thu Jul 16 16:05:28 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: a number of changes merged in from progressive.
+
+ * configure.in: add libm.
+
+ * .cvsignore: ignore some stuff that comes from test-build.mk.
+
+Wed Jul 8 00:01:30 1992 Stu Grossman (grossman at cygnus.com)
+
+ * config/mh-solaris: Use -xs when compiling so that Sun-C puts
+ a symbol-table into the executable.
+
+Tue Jul 7 00:24:52 1992 Fred Fish (fnf@cygnus.com)
+
+ * config.sub: Add es1800 (m68k-ericsson-es1800).
+
+Tue Jun 30 20:24:41 1992 D. V. Henkel-Wallace (gumby@cygnus.com)
+
+ * configure: Add program_suffix (parallel to program_prefix)
+ * Makefile.in: adjust directory-creating script for losing decstation
+
+Mon Jun 22 23:43:48 1992 Per Bothner (bothner@cygnus.com)
+
+ * configure: Minor $subdir-related fixes.
+
+Mon Jun 22 18:30:26 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * configure: fix various problems with propogating
+ makefile_target_frag in subdirs.
+ * configure.in: config libgcc if its there
+
+Fri Jun 19 15:19:40 1992 Stu Grossman (grossman at cygnus.com)
+
+ * config.sub: HPPA merge.
+
+Mon Jun 15 12:31:52 1992 Fred Fish (fnf@cygnus.com)
+
+ * config/mh-ncr3000 (INSTALL): Don't use /usr/ucb/install,
+ it is broken on ncr 3000's.
+
+Sun Jun 14 10:29:19 1992 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Replace all-bison with all-byacc in all
+ dependency lines for other tools (which now use byacc).
+
+Fri Jun 12 22:21:57 1992 John Gilmore (gnu at cygnus.com)
+
+ * config.sub: Add sun4sol2 => sparc-sun-solaris2.
+
+Tue Jun 9 17:18:11 1992 Fred Fish (fnf at cygnus.com)
+
+ * config/{mh-ncr3000, mh-sysv4}: Add INSTALL.
+
+Thu Jun 4 12:07:32 1992 Mark Eichin (eichin@cygnus.com)
+
+ * Makefile.in: make gprof rules similar to byacc rules (instead of
+ vestigal $(unsubdir) that didn't work...)
+
+Thu Jun 4 00:37:05 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * config.sub: Add support for Linux.
+ * Makefile.in: Use $(FLAGS_TO_PASS) more consistently
+ (at least for libg++).
+
+Tue Jun 02 20:03:00 1992 david d `zoo' zuhn (zoo@cygnus.com)
+
+ * configure.texi: fix doc for the -nfp option to configure
+
+Tue Jun 2 17:20:52 1992 Michael Tiemann (tiemann@cygnus.com)
+
+ * Makefile.in (all-binutils): ar needs flex, so depend on all-flex.
+
+Sun May 31 15:04:08 1992 Mark Eichin (eichin at cygnus.com)
+
+ * config.sub: changed [^-]+ to [^-][^-]* so that it works under
+ Sun sed. (BSD 4.3 sed doesn't handle [^-]+ either.)
+ * configure.in: added solaris* host_makefile_frag hook.
+
+Sun May 31 01:10:34 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config.sub: changed recognition of m68000 so that various
+ m68k types can be specified via m680[01234]0
+
+Sat May 30 21:01:06 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config.sub (basic_machine): fix sed so that '-foo' isn't
+ completely substituted out while .+'-foo' loses the '-foo'
+
+Wed May 27 23:18:52 1992 Michael Tiemann (tiemann@rtl.cygnus.com)
+
+ * config.sub ($os): Add -aout.
+
+Fri May 22 14:00:02 1992 Per Bothner (bothner@cygnus.com)
+
+ * configure: If host_makefile_frag is absolute, don't
+ prefix ${invsubdir} (relevant to libg++ auto-configure).
+
+Thu May 21 18:00:09 1992 Michael Tiemann (tiemann@rtl.cygnus.com)
+
+ * Makefile.in (tooldir): Define it.
+ (all-ld): Depend on all-flex.
+
+Sun May 10 21:45:59 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in (check): Fix libg++ special case.
+
+Fri May 8 08:31:41 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * configure: do not bury `pwd` into config.status, thus do fewer
+ pwd's.
+
+ * configure: print the "Building in" message only when building in
+ other than "." AND verbose.
+
+ * configure: remove -s, rework -v to better accomodate guested
+ configures.
+
+ * standards.texi: updated to 3 may, fixed librid <-> libdir typo.
+
+Fri May 1 18:00:50 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: macroize flags passed on recursion. remove
+ fileutils.
+
+Thu Apr 30 08:56:20 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * configure: get makesrcdir right for subdirs deeper than 1.
+
+ * Makefile.in: pass INSTALL, INSTALL_DATA, INSTALL_PROGRAM on
+ install.
+
+Fri Apr 24 15:51:51 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: don't print subdir_do or recursion lines.
+
+Fri Apr 24 15:22:04 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * standards.texi: added menu item.
+
+ * Makefile.in: build and install standards.info.
+
+ * standards.texi: new file.
+
+Wed Apr 22 18:06:55 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * configure: test for and move config.status pieces from
+ ${subdir}/.
+
+Wed Apr 22 14:38:34 1992 Fred Fish (fnf@cygnus.com)
+
+ * config/mh-delta88, config/mh-ncr3000: Replace MINUS_G with
+ CFLAGS per new configuration strategy.
+ * configure: Test for existance of files before trying to mv
+ them, to avoid numerous non-existance messages.
+
+Tue Apr 21 12:31:33 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * configure: correct final line of config.status.
+
+ * configure: patch from eggert. Avoids a protection problem if
+ the original Makefile.in is read only.
+
+ * configure: use move-if-change from gcc to create config.status.
+ Some makefiles depend on config.status to tell if a directory
+ has been reconfigured for a different host. This change
+ prevents those directories from remaking everything in the case
+ where the reconfig was only intended to rebuild a Makefile.
+
+ * configure: test for config.sub with "config.sub sun4" rather
+ than "config.sub ${host_alias}". Otherwise we can't tell a bad
+ host alias from a missing config.sub.
+
+Mon Apr 20 18:16:36 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: explicitly pass CFLAGS on recursion. no longer pass
+ MINUS_G (this can be done with CFLAGS). Default CFLAGS to -g.
+
+Fri Apr 17 18:27:51 1992 Per Bothner (bothner@cygnus.com)
+
+ * configure: mkdir ${subdir} as needed.
+
+Wed Apr 15 17:37:22 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in,configure.in: added autoconf.
+
+Wed Apr 15 17:27:34 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: no longer pass against on recursion.
+
+ * Makefile.in: added .NOEXPORT: so that stray makefile_frag
+ definitions are not inherited.
+
+ * configure: correct makesrcdir when subdir is .
+
+Tue Apr 14 11:56:09 1992 Per Bothner (bothner@cygnus.com)
+
+ * configure: Add support for 'subdirs' variable, which is
+ like 'configdirs', except that configure doesn't re-invoke
+ itself for subdirs, it just creates a Makefile for each subdir.
+ * configure.texi: Document subdirs.
+
+Mon Apr 13 18:50:16 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: added flex to configdirs
+
+Mon Apr 13 18:43:55 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: remove clean-stamps from clean.
+
+Sat Apr 11 03:52:03 1992 John Gilmore (gnu at cygnus.com)
+
+ * configure.in: Add gdbtest to configdirs.
+
+Fri Apr 10 23:11:49 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (MINUS_G): Add macro, default to -g, pass on
+ to recursive makes.
+ * configure.in: Recognize new ncr3000 config.
+
+Wed Apr 8 23:08:12 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in, configure.in: removed references to gdbm.
+
+Tue Apr 7 16:48:20 1992 Per Bothner (bothner@cygnus.com)
+
+ * config.sub: Don't canonicalize os value
+ newsos* to bsd (readline needs to check for newsos).
+ (This fix was earlier made Jan 31, but got re-broken.)
+
+Mon Apr 6 14:34:08 1992 Stu Grossman (grossman at cygnus.com)
+
+ * configure.in: sco is an os, not a vendor!
+
+ * configure: Quote $( better. Keep various shells happy.
+
+Tue Mar 31 16:32:57 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: eliminate stamp-files.
+
+Mon Mar 30 22:20:23 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: add send_pr. remove "force" from .stmp-gprof rule.
+ Supress echoing of all the "if [ -d ... $(MAKE)" lines.
+
+Wed Mar 25 15:20:04 1992 Stu Grossman (grossman@cygnus.com)
+
+ * config.sub: fix iris/iris3.
+
+Wed Mar 25 10:34:19 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * configure: re-add -rm.
+
+Tue Mar 24 23:50:16 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Maskefile.in: add .stmp-rcs to all.
+
+ * configure.in: remove gas from rs6000 build, use aix host fragment.
+
+Mon Mar 23 19:43:35 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * configure: pass down site_option during recursion.
+
+Thu Mar 19 16:49:36 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (all.cross): Add .stmp-bfd .stmp-readline.
+
+Wed Mar 18 15:29:33 1992 Mike Stump (mrs@cygnus.com)
+
+ * configure: Change exec_prefix so that it really defaults to prefix.
+
+Sat Mar 14 17:20:38 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in, configure.in: Add support for mmalloc library.
+
+Fri Mar 13 18:44:18 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: add stmp dependencies for a few more things.
+
+Thu Mar 12 04:56:24 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * configure: adjusted error message on objdir/srcdir configure
+ collision, per john's suggestion.
+
+ * Makefile.in: add libiberty stmp to all and all.cross.
+
+Wed Mar 11 02:07:52 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: remove force dependencies, add grep to all.
+
+Tue Mar 10 21:49:18 1992 K. Richard Pixley (rich@mars.cygnus.com)
+
+ * Makefile.in: drop flex. make stamp files work.
+
+ * configure: added test for conflicting configuration in srcdir,
+ remove trailing slashes from srcdir. Otherwise emacs gdb mode
+ gets cranky. use relative paths for configure and srcdir
+ whenever possible. Send some error messages to stderr that were
+ going to stdout.
+
+Tue Mar 10 18:01:55 1992 Per Bothner (bothner@cygnus.com)
+
+ * Makefile.in: Fix libg++ rule to check for gcc directory
+ before using gcc/gcc. Also pass XTRAFLAGS.
+
+Thu Mar 5 21:45:07 1992 K. Richard Pixley (rich@sendai)
+
+ * Makefile.in: added stmp-files so that directories aren't polled
+ when they are already built.
+
+ * configure.texi: fixed a node pointer problem.
+
+Thu Mar 5 12:05:58 1992 Stu Grossman (grossman at cygnus.com)
+
+ * config.sub configure.in config/mh-irix4 gdb/configure.in
+ gdb/mips-tdep.c gdb/mipsread.c gdb/procfs.c gdb/signame.h
+ gdb/tm-irix3.h gdb/tm-mips.h gdb/xm-irix4.h gdb/config/mt-irix3
+ gdb/config/mh-irix4 texinfo/configure.in: Port to SGI Irix-4.x.
+
+Wed Mar 4 02:57:46 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * configure: -recurring becomes -silent. corrected help message
+ for -site= option.
+
+ * Makefile.in: mkdir $(exec_prefix) and $(tooldir).
+
+Tue Mar 3 14:51:21 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * configure: when building Makefile for crosses, replace
+ tooldir and program_prefix. default srcdir from location of
+ config.sub. remove "for host in hosts" and "for target in
+ targets" loops.
+
+Wed Feb 26 19:48:25 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: Do not pass bindir or mandir to cvs.
+
+Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in, configure.in: removed traces of namesubdir,
+ -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced
+ copyrights to '92, changed some from Cygnus to FSF.
+
+ * configure.texi: remove most references to multiple hosts,
+ multiple targets, subdirs, etc.
+
+ * configure.man: removed rcsid. reference config.sub not
+ config.subr.
+
+ * Makefile.in: mkdir $(infodir) on install-info.
+
+Wed Feb 19 15:41:13 1992 John Gilmore (gnu at cygnus.com)
+
+ * configure.texi: Explain better about .gdbinit and about
+ the environment that configure.in sections run in.
+
+Fri Feb 7 07:55:00 1992 John Gilmore (gnu at cygnus.com)
+
+ * configure.in: Ultrix is only a decstation if it's a MIPS.
+
+Fri Jan 31 21:54:51 1992 John Gilmore (gnu at cygnus.com)
+
+ * README: DOC.configure => cfg-paper.texi.
+
+Fri Jan 31 21:48:18 1992 Stu Grossman (grossman at cygnus.com)
+
+ * config.sub (near case $os): Don't convert newsos* to bsd!
+
+Fri Jan 31 02:27:32 1992 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Reinstall change from gdb-4.3 that reduces
+ the number of copies of COPYING that go into the GDB tar file.
+
+Thu Jan 30 16:17:30 1992 Stu Grossman (grossman at cygnus.com)
+
+ * bfd/configure.in, config/mh-sco, gdb/config/mh-i386sco,
+ gdb/config/mt-i386v32, gdb/configure.in, readline/configure.in:
+ Fix SCO configuration stuff.
+
+Tue Jan 28 23:51:07 1992 Per Bothner (bothner at cygnus.com)
+
+ * Makefile.in: For libg++, make sure the -I pointing
+ to the gcc directory goes *after* all the libg++-local -I flags.
+ Also, move just-gcc dependency from just-libg++ to all-libg++.
+
+Tue Jan 28 12:56:24 1992 Stu Grossman (grossman at cygnus.com)
+
+ * configure: Change -x to -f to keep Ultrix /bin/test happy.
+
+Sat Jan 18 17:45:11 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (make-gdb.tar.Z): Remove texinfo targets.
+
+Sat Jan 18 17:03:21 1992 Fred Fish (fnf at cygnus.com)
+
+ * config.sub: Add stratus configuration frags. Also
+ submitted to FSF.
+
+Sat Jan 18 15:35:29 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (DEV_SUPPORT): add configure.man.
+
+ * config.sub(Decode manufacturer-specific): add -none*.
+
+Fri Jan 17 17:58:05 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: remove form feeds to make Sun's make happy.
+ (DEVO_SUPPORT): DOC.configure => cfg-paper.texi.
+
+Sat Jan 4 16:11:44 1992 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in (AR_FLAGS): Make quieter.
+
+Thu Jan 2 22:57:12 1992 John Gilmore (gnu at cygnus.com)
+
+ * configure.in: Add libg++.
+ * configure: When verbose, don't output the command line at each
+ level; it will be unremarkably the same as the previous version,
+ which will be the same as what the user typed.
+
+Fri Dec 27 16:26:47 1991 K. Richard Pixley (rich at cygnus.com)
+
+ * configure.in, Makefile.in: fix clean-info, add flex. add
+ fileutils.
+
+ * configure: be less sensitive to spaces in Makefile.in. Do not
+ look for sources in "..". Doing so breaks subdirectories that
+ might have their own configure. If a subdir has it's own
+ configure script, use it.
+
+Thu Dec 26 16:30:26 1991 K. Richard Pixley (rich at cygnus.com)
+
+ * cfg-paper.texi: some changes suggested by rms.
+
+Thu Dec 26 10:13:36 1991 Fred Fish (fnf at cygnus.com)
+
+ * config.sub: Merge in some small additions from the FSF version,
+ taken from the gcc distribution, to bring the Cygnus and FSF
+ versions into closer sync.
+
+Fri Dec 20 11:34:18 1991 Fred Fish (fnf at cygnus.com)
+
+ * configure.in: Changed svr4 references to sysv4.
+
+Thu Dec 19 15:54:29 1991 K. Richard Pixley (rich at cygnus.com)
+
+ * configure: added -V for version number option.
+
+Wed Dec 18 15:39:34 1991 K. Richard Pixley (rich at cygnus.com)
+
+ * DOC.configure, cfg-paper.texi: revised, updated, and texinfo'd.
+ renamed from DOC.configure to cfg-paper.texi.
+
+Mon Dec 16 23:05:19 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * configure, config.subr, config.sub: config.subr is now
+ config.sub again.
+
+Fri Dec 13 01:17:06 1991 K. Richard Pixley (rich at cygnus.com)
+
+ * configure.texi: new file, in progress.
+
+ * Makefile.in: build info file and install the man page for
+ configure.
+
+ * configure.man: new file, first cut.
+
+ * configure: find config.subr again now that configuration "none"
+ has gone. removed all traces of the -ansi option. removed all
+ traces of the -languages option.
+
+ * config.subr: resync from rms.
+
+Wed Dec 11 22:25:20 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * configure, config.sub, config.subr: merge config.sub into
+ config.subr, call the result config.subr, remove config.sub, use
+ config.subr.
+
+ * Makefile.in: revised install for dir.info.
+
+Tue Dec 10 00:04:35 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * configure.in: add decstation host makefile frag.
+
+ * Makefile.in: BISON now bison -y again. also install-gcc on
+ install. clean-gdbm on clean. infodir belongs in datadir.
+ Make directories for info install. Build dir.info here then
+ install it.
+
+Mon Dec 9 16:48:33 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: fix for bad directory tests.
+
+Sat Dec 7 00:17:01 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * configure: \{1,2\} appears to be a sysv'ism. Use a different
+ regexp. -srcdir relative was being handled incorrectly.
+
+ * Makefile.in: unwrapped some for loops so that parallel makes
+ work again and so one can focus one's attention on a particular
+ package.
+
+Fri Dec 6 00:22:08 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * configure: added PWD as a stand in for `pwd` (for speed). use
+ elif wherever possible. make -srcdir work without -objdir.
+ -objdir= commented out.
+
+Thu Dec 5 22:46:52 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * configure: +options become --options. -subdirs commented out.
+ added -host, -datadir. Renamed -destdir to -prefix. Comment in
+ Makefile now at top of generated Makefile. Removed cvs log
+ entries. added -srcdir. create .gdbinit only if there is one
+ in ${srcdir}.
+
+ * Makefile.in: idestdir and ddestdir go away. Added copyrights
+ and shift gpl to v2. Added ChangeLog if it didn't exist. docdir
+ and mandir now keyed off datadir by default.
+
+Fri Nov 22 07:38:11 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Freshly created ChangeLog.
+
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gnu/usr.bin/binutils/bfd/coff-aux.c b/gnu/usr.bin/binutils/bfd/coff-aux.c
new file mode 100644
index 00000000000..1dba9d5c465
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/coff-aux.c
@@ -0,0 +1,332 @@
+/* BFD back-end for Apple M68K COFF A/UX 3.x files.
+ Copyright 1996 Free Software Foundation, Inc.
+ Portions written by Richard Henderson <rth@tamu.edu>,
+ COMMON symbol munging cribbed from cf-m68klynx.c which was
+ written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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. */
+
+#define TARGET_SYM m68kaux_coff_vec
+#define TARGET_NAME "coff-m68k-aux"
+
+#ifndef TARG_AUX
+#define TARG_AUX
+#endif
+
+#define COFF_LONG_FILENAMES
+
+/* 4k pages */
+#define COFF_PAGE_SIZE 0x1000
+
+/* On AUX, a STYP_NOLOAD|STYP_BSS section is part of a shared library. */
+#define BSS_NOLOAD_IS_SHARED_LIBRARY
+
+#define _bfd_m68kcoff_howto_table _bfd_m68kaux_howto_table
+#define _bfd_m68kcoff_rtype2howto _bfd_m68kaux_rtype2howto
+#define _bfd_m68kcoff_howto2rtype _bfd_m68kaux_howto2rtype
+#define _bfd_m68kcoff_reloc_type_lookup _bfd_m68kaux_reloc_type_lookup
+
+/* Rather than change names lots of places, reuse the same hack */
+#define LYNX_SPECIAL_FN _bfd_m68kaux_special_fn
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#ifdef ANSI_PROTOTYPES
+struct internal_reloc;
+struct coff_link_hash_entry;
+struct internal_syment;
+#endif
+
+
+static bfd_reloc_status_type _bfd_m68kaux_special_fn
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static reloc_howto_type *coff_m68k_aux_rtype_to_howto
+ PARAMS ((bfd *, asection *, struct internal_reloc *,
+ struct coff_link_hash_entry *, struct internal_syment *,
+ bfd_vma *));
+static boolean coff_m68k_aux_link_add_one_symbol
+ PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword,
+ asection *, bfd_vma, const char *, boolean, boolean,
+ struct bfd_link_hash_entry **));
+
+
+#define coff_rtype_to_howto coff_m68k_aux_rtype_to_howto
+#define coff_link_add_one_symbol coff_m68k_aux_link_add_one_symbol
+
+
+/* Compute the addend of a reloc. If the reloc is to a common symbol,
+ the object file contains the value of the common symbol. By the
+ time this is called, the linker may be using a different symbol
+ from a different object file with a different value. Therefore, we
+ hack wildly to locate the original symbol from this file so that we
+ can make the correct adjustment. This macro sets coffsym to the
+ symbol from the original file, and uses it to set the addend value
+ correctly. If this is not a common symbol, the usual addend
+ calculation is done, except that an additional tweak is needed for
+ PC relative relocs.
+ FIXME: This macro refers to symbols and asect; these are from the
+ calling function, not the macro arguments. */
+
+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
+ { \
+ coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
+ if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
+ coffsym = (obj_symbols (abfd) \
+ + (cache_ptr->sym_ptr_ptr - symbols)); \
+ else if (ptr) \
+ coffsym = coff_symbol_from (abfd, ptr); \
+ if (coffsym != (coff_symbol_type *) NULL \
+ && coffsym->native->u.syment.n_scnum == 0) \
+ cache_ptr->addend = - coffsym->native->u.syment.n_value; \
+ else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
+ && ptr->section != (asection *) NULL) \
+ cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ else \
+ cache_ptr->addend = 0; \
+ if (ptr && (reloc.r_type == R_PCRBYTE \
+ || reloc.r_type == R_PCRWORD \
+ || reloc.r_type == R_PCRLONG)) \
+ cache_ptr->addend += asect->vma; \
+ }
+
+
+
+#include "coff/aux-coff.h" /* override coff/internal.h and coff/m68k.h */
+#include "coff-m68k.c"
+
+
+
+/* For some reason when using m68k COFF the value stored in the .text
+ section for a reference to a common symbol is the value itself plus
+ any desired offset. (taken from work done by Ian Taylor, Cygnus Support,
+ for I386 COFF). */
+
+/* If we are producing relocateable output, we need to do some
+ adjustments to the object file that are not done by the
+ bfd_perform_relocation function. This function is called by every
+ reloc type to make any required adjustments. */
+
+static bfd_reloc_status_type
+_bfd_m68kaux_special_fn (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ symvalue diff;
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ if (bfd_is_com_section (symbol->section))
+ {
+ /* We are relocating a common symbol. The current value in the
+ object file is ORIG + OFFSET, where ORIG is the value of the
+ common symbol as seen by the object file when it was compiled
+ (this may be zero if the symbol was undefined) and OFFSET is
+ the offset into the common symbol (normally zero, but may be
+ non-zero when referring to a field in a common structure).
+ ORIG is the negative of reloc_entry->addend, which is set by
+ the CALC_ADDEND macro below. We want to replace the value in
+ the object file with NEW + OFFSET, where NEW is the value of
+ the common symbol which we are going to put in the final
+ object file. NEW is symbol->value. */
+ diff = symbol->value + reloc_entry->addend;
+ }
+ else
+ {
+ /* For some reason bfd_perform_relocation always effectively
+ ignores the addend for a COFF target when producing
+ relocateable output. This seems to be always wrong for 386
+ COFF, so we handle the addend here instead. */
+ diff = reloc_entry->addend;
+ }
+
+#define DOIT(x) \
+ x = ((x & ~howto->dst_mask) | \
+ (((x & howto->src_mask) + diff) & howto->dst_mask))
+
+ if (diff != 0)
+ {
+ reloc_howto_type *howto = reloc_entry->howto;
+ unsigned char *addr = (unsigned char *) data + reloc_entry->address;
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = bfd_get_8 (abfd, addr);
+ DOIT (x);
+ bfd_put_8 (abfd, x, addr);
+ }
+ break;
+
+ case 1:
+ {
+ short x = bfd_get_16 (abfd, addr);
+ DOIT (x);
+ bfd_put_16 (abfd, x, addr);
+ }
+ break;
+
+ case 2:
+ {
+ long x = bfd_get_32 (abfd, addr);
+ DOIT (x);
+ bfd_put_32 (abfd, x, addr);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ /* Now let bfd_perform_relocation finish everything up. */
+ return bfd_reloc_continue;
+}
+
+
+/* coff-m68k.c uses the special COFF backend linker. We need to
+ adjust common symbols. */
+
+/*ARGSUSED*/
+static reloc_howto_type *
+coff_m68k_aux_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
+ bfd *abfd;
+ asection *sec;
+ struct internal_reloc *rel;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma *addendp;
+{
+ arelent relent;
+ reloc_howto_type *howto;
+
+ RTYPE2HOWTO (&relent, rel);
+
+ howto = relent.howto;
+
+ if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
+ {
+ /* This is a common symbol. The section contents include the
+ size (sym->n_value) as an addend. The relocate_section
+ function will be adding in the final value of the symbol. We
+ need to subtract out the current size in order to get the
+ correct result. */
+ BFD_ASSERT (h != NULL);
+ *addendp -= sym->n_value;
+ }
+
+ /* If the output symbol is common (in which case this must be a
+ relocateable link), we need to add in the final size of the
+ common symbol. */
+ if (h != NULL && h->root.type == bfd_link_hash_common)
+ *addendp += h->root.u.c.size;
+
+ return howto;
+}
+
+
+/* We need non-absolute symbols to override absolute symbols. This
+ mirrors Apple's "solution" to let a static library symbol override
+ a shared library symbol. On the whole not a good thing, given how
+ shared libraries work here, but can work if you are careful with
+ what you include in the shared object. */
+
+boolean
+coff_m68k_aux_link_add_one_symbol (info, abfd, name, flags, section, value,
+ string, copy, collect, hashp)
+ struct bfd_link_info *info;
+ bfd *abfd;
+ const char *name;
+ flagword flags;
+ asection *section;
+ bfd_vma value;
+ const char *string;
+ boolean copy;
+ boolean collect;
+ struct bfd_link_hash_entry **hashp;
+{
+ struct bfd_link_hash_entry *h;
+
+ if ((flags & (BSF_WARNING | BSF_CONSTRUCTOR | BSF_WEAK)) == 0 &&
+ !bfd_is_und_section (section) &&
+ !bfd_is_com_section (section))
+ {
+ /* The new symbol is a definition or an indirect definition */
+
+ /* This bit copied from linker.c */
+ if (hashp != NULL && *hashp != NULL)
+ {
+ h = *hashp;
+ BFD_ASSERT (strcmp (h->root.string, name) == 0);
+ }
+ else
+ {
+ h = bfd_link_hash_lookup (info->hash, name, true, copy, false);
+ if (h == NULL)
+ {
+ if (hashp != NULL)
+ *hashp = NULL;
+ return false;
+ }
+ }
+
+ if (info->notice_hash != (struct bfd_hash_table *) NULL
+ && (bfd_hash_lookup (info->notice_hash, name, false, false)
+ != (struct bfd_hash_entry *) NULL))
+ {
+ if (! (*info->callbacks->notice) (info, name, abfd, section, value))
+ return false;
+ }
+
+ if (hashp != (struct bfd_link_hash_entry **) NULL)
+ *hashp = h;
+ /* end duplication from linker.c */
+
+ if (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_indirect)
+ {
+ asection *msec;
+
+ if (h->type == bfd_link_hash_defined)
+ msec = h->u.def.section;
+ else
+ msec = bfd_ind_section_ptr;
+
+ if (bfd_is_abs_section (msec) && !bfd_is_abs_section (section))
+ {
+ h->u.def.section = section;
+ h->u.def.value = value;
+ return true;
+ }
+ else if (bfd_is_abs_section (section) && !bfd_is_abs_section (msec))
+ return true;
+ }
+ }
+
+ /* If we didn't exit early, finish processing in the generic routine */
+ return _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
+ value, string, copy, collect,
+ hashp);
+}
diff --git a/gnu/usr.bin/binutils/bfd/elf64-mips.c b/gnu/usr.bin/binutils/bfd/elf64-mips.c
new file mode 100644
index 00000000000..978b921bb49
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/elf64-mips.c
@@ -0,0 +1,1931 @@
+/* MIPS-specific support for 64-bit ELF
+ Copyright 1996 Free Software Foundation, Inc.
+ Ian Lance Taylor, Cygnus Support
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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. */
+
+/* This file supports the 64-bit MIPS ELF ABI.
+
+ The MIPS 64-bit ELF ABI uses an unusual reloc format. This file
+ overrides the usual ELF reloc handling, and handles reading and
+ writing the relocations here. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "genlink.h"
+#include "elf-bfd.h"
+#include "elf/mips.h"
+
+/* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to
+ use ECOFF. However, we support it anyhow for an easier changeover. */
+#include "coff/sym.h"
+#include "coff/symconst.h"
+#include "coff/internal.h"
+#include "coff/ecoff.h"
+/* The 64 bit versions of the mdebug data structures are in alpha.h. */
+#include "coff/alpha.h"
+#define ECOFF_64
+#include "ecoffswap.h"
+
+static void mips_elf64_swap_reloc_in
+ PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
+ Elf64_Mips_Internal_Rel *));
+static void mips_elf64_swap_reloca_in
+ PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
+ Elf64_Mips_Internal_Rela *));
+#if 0
+static void mips_elf64_swap_reloc_out
+ PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
+ Elf64_Mips_External_Rel *));
+#endif
+static void mips_elf64_swap_reloca_out
+ PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
+ Elf64_Mips_External_Rela *));
+static reloc_howto_type *mips_elf64_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *));
+static boolean mips_elf64_slurp_one_reloc_table
+ PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
+static boolean mips_elf64_slurp_reloc_table
+ PARAMS ((bfd *, asection *, asymbol **));
+static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
+static boolean mips_elf64_section_from_shdr
+ PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
+static boolean mips_elf64_section_processing
+ PARAMS ((bfd *, Elf_Internal_Shdr *));
+
+/* The relocation types. */
+
+enum mips_elf64_reloc_type
+{
+ R_MIPS_NONE = 0,
+ R_MIPS_16 = 1,
+ R_MIPS_32 = 2,
+ R_MIPS_ADD = 2,
+ R_MIPS_REL32 = 3,
+ R_MIPS_REL = 3,
+ R_MIPS_26 = 4,
+ R_MIPS_HI16 = 5,
+ R_MIPS_LO16 = 6,
+ R_MIPS_GPREL16 = 7,
+ R_MIPS_GPREL = 7,
+ R_MIPS_LITERAL = 8,
+ R_MIPS_GOT16 = 9,
+ R_MIPS_GOT = 9,
+ R_MIPS_PC16 = 10,
+ R_MIPS_CALL16 = 11,
+ R_MIPS_CALL = 11,
+ R_MIPS_GPREL32 = 12,
+ R_MIPS_SHIFT5 = 16,
+ R_MIPS_SHIFT6 = 17,
+ R_MIPS_64 = 18,
+ R_MIPS_GOT_DISP = 19,
+ R_MIPS_GOT_PAGE = 20,
+ R_MIPS_GOT_OFST = 21,
+ R_MIPS_GOT_HI16 = 22,
+ R_MIPS_GOT_LO16 = 23,
+ R_MIPS_SUB = 24,
+ R_MIPS_INSERT_A = 25,
+ R_MIPS_INSERT_B = 26,
+ R_MIPS_DELETE = 27,
+ R_MIPS_HIGHER = 28,
+ R_MIPS_HIGHEST = 29,
+ R_MIPS_CALL_HI16 = 30,
+ R_MIPS_CALL_LO16 = 31,
+ R_MIPS_SCN_DISP = 32,
+ R_MIPS_REL16 = 33,
+ R_MIPS_ADD_IMMEDIATE = 34,
+ R_MIPS_PJUMP = 35,
+ R_MIPS_RELGOT = 36
+};
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
+ from smaller values. Start with zero, widen, *then* decrement. */
+#define MINUS_ONE (((bfd_vma)0) - 1)
+
+/* The relocation table used for SHT_REL sections. */
+
+static reloc_howto_type mips_elf64_howto_table_rel[] =
+{
+ /* No relocation. */
+ HOWTO (R_MIPS_NONE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_NONE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit relocation. */
+ HOWTO (R_MIPS_16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit relocation. */
+ HOWTO (R_MIPS_32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit symbol relative relocation. */
+ HOWTO (R_MIPS_REL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_REL32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 26 bit branch address. */
+ HOWTO (R_MIPS_26, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ /* This needs complex overflow
+ detection, because the upper four
+ bits must match the PC. */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_26", /* name */
+ true, /* partial_inplace */
+ 0x3ffffff, /* src_mask */
+ 0x3ffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 16 bits of symbol value. */
+ HOWTO (R_MIPS_HI16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_hi16_reloc, /* special_function */
+ "R_MIPS_HI16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 16 bits of symbol value. */
+ HOWTO (R_MIPS_LO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_lo16_reloc, /* special_function */
+ "R_MIPS_LO16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* GP relative reference. */
+ HOWTO (R_MIPS_GPREL16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_gprel16_reloc, /* special_function */
+ "R_MIPS_GPREL16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Reference to literal section. */
+ HOWTO (R_MIPS_LITERAL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_gprel16_reloc, /* special_function */
+ "R_MIPS_LITERAL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Reference to global offset table. */
+ HOWTO (R_MIPS_GOT16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_got16_reloc, /* special_function */
+ "R_MIPS_GOT16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit PC relative reference. */
+ HOWTO (R_MIPS_PC16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit call through global offset table. */
+ /* FIXME: This is not handled correctly. */
+ HOWTO (R_MIPS_CALL16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_CALL16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit GP relative reference. */
+ HOWTO (R_MIPS_GPREL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ _bfd_mips_elf_gprel32_reloc, /* special_function */
+ "R_MIPS_GPREL32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 13 },
+ { 14 },
+ { 15 },
+
+ /* A 5 bit shift field. */
+ HOWTO (R_MIPS_SHIFT5, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 5, /* bitsize */
+ false, /* pc_relative */
+ 6, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_SHIFT5", /* name */
+ true, /* partial_inplace */
+ 0x000007c0, /* src_mask */
+ 0x000007c0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 6 bit shift field. */
+ /* FIXME: This is not handled correctly; a special function is
+ needed to put the most significant bit in the right place. */
+ HOWTO (R_MIPS_SHIFT6, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 6, /* bitsize */
+ false, /* pc_relative */
+ 6, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_SHIFT6", /* name */
+ true, /* partial_inplace */
+ 0x000007c4, /* src_mask */
+ 0x000007c4, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 64 bit relocation. */
+ HOWTO (R_MIPS_64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_64", /* name */
+ true, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Displacement in the global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_DISP, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_DISP", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Displacement to page pointer in the global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_PAGE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_PAGE", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Offset from page pointer in the global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_OFST, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_OFST", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_HI16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_HI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_LO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_LO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 64 bit substraction. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_SUB, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_SUB", /* name */
+ true, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Insert the addend as an instruction. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_INSERT_A, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_INSERT_A", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Insert the addend as an instruction, and change all relocations
+ to refer to the old instruction at the address. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_INSERT_B, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_INSERT_B", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Delete a 32 bit instruction. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_DELETE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_DELETE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Get the higher value of a 64 bit addend. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_HIGHER, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_HIGHER", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Get the highest value of a 64 bit addend. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_HIGHEST, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_HIGHEST", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_CALL_HI16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_CALL_HI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_CALL_LO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_CALL_LO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* I'm not sure what the remaining relocs are, but they are defined
+ on Irix 6. */
+
+ HOWTO (R_MIPS_SCN_DISP, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_SCN_DISP", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_MIPS_REL16, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_REL16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_ADD_IMMEDIATE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PJUMP, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_PJUMP", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_MIPS_RELGOT, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_RELGOT", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false) /* pcrel_offset */
+};
+
+/* The relocation table used for SHT_RELA sections. */
+
+static reloc_howto_type mips_elf64_howto_table_rela[] =
+{
+ /* No relocation. */
+ HOWTO (R_MIPS_NONE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_NONE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit relocation. */
+ HOWTO (R_MIPS_16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_16", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit relocation. */
+ HOWTO (R_MIPS_32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_32", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit symbol relative relocation. */
+ HOWTO (R_MIPS_REL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_REL32", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 26 bit branch address. */
+ HOWTO (R_MIPS_26, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ /* This needs complex overflow
+ detection, because the upper four
+ bits must match the PC. */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_26", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0x3ffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 16 bits of symbol value. */
+ HOWTO (R_MIPS_HI16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_HI16", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 16 bits of symbol value. */
+ HOWTO (R_MIPS_LO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_LO16", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* GP relative reference. */
+ HOWTO (R_MIPS_GPREL16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_gprel16_reloc, /* special_function */
+ "R_MIPS_GPREL16", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Reference to literal section. */
+ HOWTO (R_MIPS_LITERAL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_gprel16_reloc, /* special_function */
+ "R_MIPS_LITERAL", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Reference to global offset table. */
+ /* FIXME: This is not handled correctly. */
+ HOWTO (R_MIPS_GOT16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit PC relative reference. */
+ HOWTO (R_MIPS_PC16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC16", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit call through global offset table. */
+ /* FIXME: This is not handled correctly. */
+ HOWTO (R_MIPS_CALL16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_CALL16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit GP relative reference. */
+ HOWTO (R_MIPS_GPREL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ _bfd_mips_elf_gprel32_reloc, /* special_function */
+ "R_MIPS_GPREL32", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 13 },
+ { 14 },
+ { 15 },
+
+ /* A 5 bit shift field. */
+ HOWTO (R_MIPS_SHIFT5, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 5, /* bitsize */
+ false, /* pc_relative */
+ 6, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_SHIFT5", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0x000007c0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 6 bit shift field. */
+ /* FIXME: This is not handled correctly; a special function is
+ needed to put the most significant bit in the right place. */
+ HOWTO (R_MIPS_SHIFT6, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 6, /* bitsize */
+ false, /* pc_relative */
+ 6, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_SHIFT6", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0x000007c4, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 64 bit relocation. */
+ HOWTO (R_MIPS_64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_64", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Displacement in the global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_DISP, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_DISP", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Displacement to page pointer in the global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_PAGE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_PAGE", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Offset from page pointer in the global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_OFST, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_OFST", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_HI16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_HI16", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_LO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_LO16", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 64 bit substraction. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_SUB, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_SUB", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Insert the addend as an instruction. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_INSERT_A, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_INSERT_A", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Insert the addend as an instruction, and change all relocations
+ to refer to the old instruction at the address. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_INSERT_B, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_INSERT_B", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Delete a 32 bit instruction. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_DELETE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_DELETE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Get the higher value of a 64 bit addend. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_HIGHER, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_HIGHER", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Get the highest value of a 64 bit addend. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_HIGHEST, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_HIGHEST", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_CALL_HI16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_CALL_HI16", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_CALL_LO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_CALL_LO16", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* I'm not sure what the remaining relocs are, but they are defined
+ on Irix 6. */
+
+ HOWTO (R_MIPS_SCN_DISP, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_SCN_DISP", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_MIPS_REL16, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_REL16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_ADD_IMMEDIATE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PJUMP, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_PJUMP", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_MIPS_RELGOT, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_RELGOT", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false) /* pcrel_offset */
+};
+
+/* Swap in a MIPS 64-bit Rel reloc. */
+
+static void
+mips_elf64_swap_reloc_in (abfd, src, dst)
+ bfd *abfd;
+ const Elf64_Mips_External_Rel *src;
+ Elf64_Mips_Internal_Rel *dst;
+{
+ dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
+ dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
+ dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
+ dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
+ dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
+ dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
+}
+
+/* Swap in a MIPS 64-bit Rela reloc. */
+
+static void
+mips_elf64_swap_reloca_in (abfd, src, dst)
+ bfd *abfd;
+ const Elf64_Mips_External_Rela *src;
+ Elf64_Mips_Internal_Rela *dst;
+{
+ dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
+ dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
+ dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
+ dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
+ dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
+ dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
+ dst->r_addend = bfd_h_get_64 (abfd, (bfd_byte *) src->r_addend);
+}
+
+#if 0
+
+/* This is not currently used. */
+
+/* Swap out a MIPS 64-bit Rel reloc. */
+
+static void
+mips_elf64_swap_reloc_out (abfd, src, dst)
+ bfd *abfd;
+ const Elf64_Mips_Internal_Rel *src;
+ Elf64_Mips_External_Rel *dst;
+{
+ bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
+ bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
+ bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
+ bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
+ bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
+ bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
+}
+
+#endif /* 0 */
+
+/* Swap out a MIPS 64-bit Rela reloc. */
+
+static void
+mips_elf64_swap_reloca_out (abfd, src, dst)
+ bfd *abfd;
+ const Elf64_Mips_Internal_Rela *src;
+ Elf64_Mips_External_Rela *dst;
+{
+ bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
+ bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
+ bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
+ bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
+ bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
+ bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
+ bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
+}
+
+/* A mapping from BFD reloc types to MIPS ELF reloc types. */
+
+struct elf_reloc_map
+{
+ bfd_reloc_code_real_type bfd_reloc_val;
+ enum mips_elf64_reloc_type elf_reloc_val;
+};
+
+static CONST struct elf_reloc_map mips_reloc_map[] =
+{
+ { BFD_RELOC_NONE, R_MIPS_NONE, },
+ { BFD_RELOC_16, R_MIPS_16 },
+ { BFD_RELOC_32, R_MIPS_32 },
+ { BFD_RELOC_64, R_MIPS_64 },
+ { BFD_RELOC_CTOR, R_MIPS_64 },
+ { BFD_RELOC_32_PCREL, R_MIPS_REL32 },
+ { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
+ { BFD_RELOC_HI16_S, R_MIPS_HI16 },
+ { BFD_RELOC_LO16, R_MIPS_LO16 },
+ { BFD_RELOC_MIPS_GPREL, R_MIPS_GPREL16 },
+ { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
+ { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
+ { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
+ { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
+ { BFD_RELOC_MIPS_GPREL32, R_MIPS_GPREL32 },
+ { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
+ { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
+ { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
+ { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 }
+};
+
+/* Given a BFD reloc type, return a howto structure. */
+
+static reloc_howto_type *
+mips_elf64_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++)
+ {
+ if (mips_reloc_map[i].bfd_reloc_val == code)
+ {
+ int v;
+
+ v = (int) mips_reloc_map[i].elf_reloc_val;
+ return &mips_elf64_howto_table_rel[v];
+ }
+ }
+
+ return NULL;
+}
+
+/* Since each entry in an SHT_REL or SHT_RELA section can represent up
+ to three relocs, we must tell the user to allocate more space. */
+
+static long
+mips_elf64_get_reloc_upper_bound (abfd, sec)
+ bfd *abfd;
+ asection *sec;
+{
+ return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
+}
+
+/* Read the relocations from one reloc section. */
+
+static boolean
+mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
+ bfd *abfd;
+ asection *asect;
+ asymbol **symbols;
+ const Elf_Internal_Shdr *rel_hdr;
+{
+ PTR allocated = NULL;
+ bfd_byte *native_relocs;
+ arelent *relents;
+ arelent *relent;
+ unsigned int count;
+ unsigned int i;
+ int entsize;
+ reloc_howto_type *howto_table;
+
+ allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
+ if (allocated == NULL)
+ goto error_return;
+
+ if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
+ || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
+ goto error_return;
+
+ native_relocs = (bfd_byte *) allocated;
+
+ relents = asect->relocation + asect->reloc_count;
+
+ entsize = rel_hdr->sh_entsize;
+ BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
+ || entsize == sizeof (Elf64_Mips_External_Rela));
+
+ count = rel_hdr->sh_size / entsize;
+
+ if (entsize == sizeof (Elf64_Mips_External_Rel))
+ howto_table = mips_elf64_howto_table_rel;
+ else
+ howto_table = mips_elf64_howto_table_rela;
+
+ relent = relents;
+ for (i = 0; i < count; i++, native_relocs += entsize)
+ {
+ Elf64_Mips_Internal_Rela rela;
+ boolean used_sym, used_ssym;
+ int ir;
+
+ if (entsize == sizeof (Elf64_Mips_External_Rela))
+ mips_elf64_swap_reloca_in (abfd,
+ (Elf64_Mips_External_Rela *) native_relocs,
+ &rela);
+ else
+ {
+ Elf64_Mips_Internal_Rel rel;
+
+ mips_elf64_swap_reloc_in (abfd,
+ (Elf64_Mips_External_Rel *) native_relocs,
+ &rel);
+ rela.r_offset = rel.r_offset;
+ rela.r_sym = rel.r_sym;
+ rela.r_ssym = rel.r_ssym;
+ rela.r_type3 = rel.r_type3;
+ rela.r_type2 = rel.r_type2;
+ rela.r_type = rel.r_type;
+ rela.r_addend = 0;
+ }
+
+ /* Each entry represents up to three actual relocations. */
+
+ used_sym = false;
+ used_ssym = false;
+ for (ir = 0; ir < 3; ir++)
+ {
+ enum mips_elf64_reloc_type type;
+
+ switch (ir)
+ {
+ default:
+ abort ();
+ case 0:
+ type = (enum mips_elf64_reloc_type) rela.r_type;
+ break;
+ case 1:
+ type = (enum mips_elf64_reloc_type) rela.r_type2;
+ break;
+ case 2:
+ type = (enum mips_elf64_reloc_type) rela.r_type3;
+ break;
+ }
+
+ if (type == R_MIPS_NONE)
+ {
+ /* There are no more relocations in this entry. If this
+ is the first entry, we need to generate a dummy
+ relocation so that the generic linker knows that
+ there has been a break in the sequence of relocations
+ applying to a particular address. */
+ if (ir == 0)
+ {
+ relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ relent->address = rela.r_offset;
+ else
+ relent->address = rela.r_offset - asect->vma;
+ relent->addend = 0;
+ relent->howto = &howto_table[(int) R_MIPS_NONE];
+ ++relent;
+ }
+ break;
+ }
+
+ /* Some types require symbols, whereas some do not. */
+ switch (type)
+ {
+ case R_MIPS_NONE:
+ case R_MIPS_LITERAL:
+ case R_MIPS_INSERT_A:
+ case R_MIPS_INSERT_B:
+ case R_MIPS_DELETE:
+ relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ break;
+
+ default:
+ if (! used_sym)
+ {
+ if (rela.r_sym == 0)
+ relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ else
+ {
+ asymbol **ps, *s;
+
+ ps = symbols + rela.r_sym - 1;
+ s = *ps;
+ if ((s->flags & BSF_SECTION_SYM) == 0)
+ relent->sym_ptr_ptr = ps;
+ else
+ relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
+ }
+
+ used_sym = true;
+ }
+ else if (! used_ssym)
+ {
+ switch (rela.r_ssym)
+ {
+ case RSS_UNDEF:
+ relent->sym_ptr_ptr =
+ bfd_abs_section_ptr->symbol_ptr_ptr;
+ break;
+
+ case RSS_GP:
+ case RSS_GP0:
+ case RSS_LOC:
+ /* FIXME: I think these need to be handled using
+ special howto structures. */
+ BFD_ASSERT (0);
+ break;
+
+ default:
+ BFD_ASSERT (0);
+ break;
+ }
+
+ used_ssym = true;
+ }
+ else
+ relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+
+ break;
+ }
+
+ /* The address of an ELF reloc is section relative for an
+ object file, and absolute for an executable file or
+ shared library. The address of a BFD reloc is always
+ section relative. */
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ relent->address = rela.r_offset;
+ else
+ relent->address = rela.r_offset - asect->vma;
+
+ relent->addend = rela.r_addend;
+
+ relent->howto = &howto_table[(int) type];
+
+ ++relent;
+ }
+ }
+
+ asect->reloc_count += relent - relents;
+
+ if (allocated != NULL)
+ free (allocated);
+
+ return true;
+
+ error_return:
+ if (allocated != NULL)
+ free (allocated);
+ return false;
+}
+
+/* Read the relocations. On Irix 6, there can be two reloc sections
+ associated with a single data section. */
+
+static boolean
+mips_elf64_slurp_reloc_table (abfd, asect, symbols)
+ bfd *abfd;
+ asection *asect;
+ asymbol **symbols;
+{
+ struct bfd_elf_section_data * const d = elf_section_data (asect);
+
+ if (asect->relocation != NULL
+ || (asect->flags & SEC_RELOC) == 0
+ || asect->reloc_count == 0)
+ return true;
+
+ /* Allocate space for 3 arelent structures for each Rel structure. */
+ asect->relocation = ((arelent *)
+ bfd_alloc (abfd,
+ asect->reloc_count * 3 * sizeof (arelent)));
+ if (asect->relocation == NULL)
+ return false;
+
+ /* The slurp_one_reloc_table routine increments reloc_count. */
+ asect->reloc_count = 0;
+
+ if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
+ return false;
+ if (d->rel_hdr2 != NULL)
+ {
+ if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
+ d->rel_hdr2))
+ return false;
+ }
+
+ return true;
+}
+
+/* Write out the relocations. */
+
+static void
+mips_elf64_write_relocs (abfd, sec, data)
+ bfd *abfd;
+ asection *sec;
+ PTR data;
+{
+ boolean *failedp = (boolean *) data;
+ unsigned int count;
+ Elf_Internal_Shdr *rela_hdr;
+ Elf64_Mips_External_Rela *ext_rela;
+ unsigned int idx;
+ asymbol *last_sym = 0;
+ int last_sym_idx = 0;
+
+ /* If we have already failed, don't do anything. */
+ if (*failedp)
+ return;
+
+ if ((sec->flags & SEC_RELOC) == 0)
+ return;
+
+ /* The linker backend writes the relocs out itself, and sets the
+ reloc_count field to zero to inhibit writing them here. Also,
+ sometimes the SEC_RELOC flag gets set even when there aren't any
+ relocs. */
+ if (sec->reloc_count == 0)
+ return;
+
+ /* We can combine up to three relocs that refer to the same address
+ if the latter relocs have no associated symbol. */
+ count = 0;
+ for (idx = 0; idx < sec->reloc_count; idx++)
+ {
+ bfd_vma addr;
+ unsigned int i;
+
+ ++count;
+
+ addr = sec->orelocation[idx]->address;
+ for (i = 0; i < 2; i++)
+ {
+ arelent *r;
+
+ if (idx + 1 >= sec->reloc_count)
+ break;
+ r = sec->orelocation[idx + 1];
+ if (r->address != addr
+ || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
+ || (*r->sym_ptr_ptr)->value != 0)
+ break;
+
+ /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
+
+ ++idx;
+ }
+ }
+
+ rela_hdr = &elf_section_data (sec)->rel_hdr;
+
+ rela_hdr->sh_size = rela_hdr->sh_entsize * count;
+ rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
+ if (rela_hdr->contents == NULL)
+ {
+ *failedp = true;
+ return;
+ }
+
+ ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
+ for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
+ {
+ arelent *ptr;
+ Elf64_Mips_Internal_Rela int_rela;
+ asymbol *sym;
+ int n;
+ unsigned int i;
+
+ ptr = sec->orelocation[idx];
+
+ /* The address of an ELF reloc is section relative for an object
+ file, and absolute for an executable file or shared library.
+ The address of a BFD reloc is always section relative. */
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ int_rela.r_offset = ptr->address;
+ else
+ int_rela.r_offset = ptr->address + sec->vma;
+
+ sym = *ptr->sym_ptr_ptr;
+ if (sym == last_sym)
+ n = last_sym_idx;
+ else
+ {
+ last_sym = sym;
+ n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+ if (n < 0)
+ {
+ *failedp = true;
+ return;
+ }
+ last_sym_idx = n;
+ }
+
+ int_rela.r_sym = n;
+
+ int_rela.r_addend = ptr->addend;
+
+ int_rela.r_ssym = RSS_UNDEF;
+
+ if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
+ && ! _bfd_elf_validate_reloc (abfd, ptr))
+ {
+ *failedp = true;
+ return;
+ }
+
+ int_rela.r_type = ptr->howto->type;
+ int_rela.r_type2 = (int) R_MIPS_NONE;
+ int_rela.r_type3 = (int) R_MIPS_NONE;
+
+ for (i = 0; i < 2; i++)
+ {
+ arelent *r;
+
+ if (idx + 1 >= sec->reloc_count)
+ break;
+ r = sec->orelocation[idx + 1];
+ if (r->address != ptr->address
+ || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
+ || (*r->sym_ptr_ptr)->value != 0)
+ break;
+
+ /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
+
+ if (i == 0)
+ int_rela.r_type2 = r->howto->type;
+ else
+ int_rela.r_type3 = r->howto->type;
+
+ ++idx;
+ }
+
+ mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
+ }
+
+ BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
+ == count);
+}
+
+/* Handle a 64-bit MIPS ELF specific section. */
+
+static boolean
+mips_elf64_section_from_shdr (abfd, hdr, name)
+ bfd *abfd;
+ Elf_Internal_Shdr *hdr;
+ char *name;
+{
+ if (! _bfd_mips_elf_section_from_shdr (abfd, hdr, name))
+ return false;
+
+ /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
+ set the gp value based on what we find. We may see both
+ SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
+ they should agree. */
+ if (hdr->sh_type == SHT_MIPS_OPTIONS)
+ {
+ bfd_byte *contents, *l, *lend;
+
+ contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
+ if (contents == NULL)
+ return false;
+ if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
+ (file_ptr) 0, hdr->sh_size))
+ {
+ free (contents);
+ return false;
+ }
+ l = contents;
+ lend = contents + hdr->sh_size;
+ while (l + sizeof (Elf_External_Options) <= lend)
+ {
+ Elf_Internal_Options intopt;
+
+ bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
+ &intopt);
+ if (intopt.kind == ODK_REGINFO)
+ {
+ Elf64_Internal_RegInfo intreg;
+
+ bfd_mips_elf64_swap_reginfo_in
+ (abfd,
+ ((Elf64_External_RegInfo *)
+ (l + sizeof (Elf_External_Options))),
+ &intreg);
+ elf_gp (abfd) = intreg.ri_gp_value;
+ }
+ l += intopt.size;
+ }
+ free (contents);
+ }
+
+ return true;
+}
+
+/* Work over a section just before writing it out. We update the GP
+ value in the SHT_MIPS_OPTIONS section based on the value we are
+ using. */
+
+static boolean
+mips_elf64_section_processing (abfd, hdr)
+ bfd *abfd;
+ Elf_Internal_Shdr *hdr;
+{
+ if (hdr->sh_type == SHT_MIPS_OPTIONS
+ && hdr->bfd_section != NULL
+ && elf_section_data (hdr->bfd_section) != NULL
+ && elf_section_data (hdr->bfd_section)->tdata != NULL)
+ {
+ bfd_byte *contents, *l, *lend;
+
+ /* We stored the section contents in the elf_section_data tdata
+ field in the set_section_contents routine. We save the
+ section contents so that we don't have to read them again.
+ At this point we know that elf_gp is set, so we can look
+ through the section contents to see if there is an
+ ODK_REGINFO structure. */
+
+ contents = (bfd_byte *) elf_section_data (hdr->bfd_section)->tdata;
+ l = contents;
+ lend = contents + hdr->sh_size;
+ while (l + sizeof (Elf_External_Options) <= lend)
+ {
+ Elf_Internal_Options intopt;
+
+ bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
+ &intopt);
+ if (intopt.kind == ODK_REGINFO)
+ {
+ bfd_byte buf[8];
+
+ if (bfd_seek (abfd,
+ (hdr->sh_offset
+ + (l - contents)
+ + sizeof (Elf_External_Options)
+ + (sizeof (Elf64_External_RegInfo) - 8)),
+ SEEK_SET) == -1)
+ return false;
+ bfd_h_put_64 (abfd, elf_gp (abfd), buf);
+ if (bfd_write (buf, 1, 8, abfd) != 8)
+ return false;
+ }
+ l += intopt.size;
+ }
+ }
+
+ return _bfd_mips_elf_section_processing (abfd, hdr);
+}
+
+/* ECOFF swapping routines. These are used when dealing with the
+ .mdebug section, which is in the ECOFF debugging format. */
+static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
+{
+ /* Symbol table magic number. */
+ magicSym2,
+ /* Alignment of debugging information. E.g., 4. */
+ 8,
+ /* Sizes of external symbolic information. */
+ sizeof (struct hdr_ext),
+ sizeof (struct dnr_ext),
+ sizeof (struct pdr_ext),
+ sizeof (struct sym_ext),
+ sizeof (struct opt_ext),
+ sizeof (struct fdr_ext),
+ sizeof (struct rfd_ext),
+ sizeof (struct ext_ext),
+ /* Functions to swap in external symbolic data. */
+ ecoff_swap_hdr_in,
+ ecoff_swap_dnr_in,
+ ecoff_swap_pdr_in,
+ ecoff_swap_sym_in,
+ ecoff_swap_opt_in,
+ ecoff_swap_fdr_in,
+ ecoff_swap_rfd_in,
+ ecoff_swap_ext_in,
+ _bfd_ecoff_swap_tir_in,
+ _bfd_ecoff_swap_rndx_in,
+ /* Functions to swap out external symbolic data. */
+ ecoff_swap_hdr_out,
+ ecoff_swap_dnr_out,
+ ecoff_swap_pdr_out,
+ ecoff_swap_sym_out,
+ ecoff_swap_opt_out,
+ ecoff_swap_fdr_out,
+ ecoff_swap_rfd_out,
+ ecoff_swap_ext_out,
+ _bfd_ecoff_swap_tir_out,
+ _bfd_ecoff_swap_rndx_out,
+ /* Function to read in symbolic data. */
+ _bfd_mips_elf_read_ecoff_info
+};
+
+/* Relocations in the 64 bit MIPS ELF ABI are more complex than in
+ standard ELF. This structure is used to redirect the relocation
+ handling routines. */
+
+const struct elf_size_info mips_elf64_size_info =
+{
+ sizeof (Elf64_External_Ehdr),
+ sizeof (Elf64_External_Phdr),
+ sizeof (Elf64_External_Shdr),
+ sizeof (Elf64_Mips_External_Rel),
+ sizeof (Elf64_Mips_External_Rela),
+ sizeof (Elf64_External_Sym),
+ sizeof (Elf64_External_Dyn),
+ sizeof (Elf_External_Note),
+ 64, /* arch_size */
+ 8, /* file_align */
+ ELFCLASS64,
+ EV_CURRENT,
+ bfd_elf64_write_out_phdrs,
+ bfd_elf64_write_shdrs_and_ehdr,
+ mips_elf64_write_relocs,
+ bfd_elf64_swap_symbol_out,
+ mips_elf64_slurp_reloc_table,
+ bfd_elf64_slurp_symbol_table,
+ bfd_elf64_swap_dyn_in
+};
+
+#define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
+#define TARGET_LITTLE_NAME "elf64-littlemips"
+#define TARGET_BIG_SYM bfd_elf64_bigmips_vec
+#define TARGET_BIG_NAME "elf64-bigmips"
+#define ELF_ARCH bfd_arch_mips
+#define ELF_MACHINE_CODE EM_MIPS
+#define ELF_MAXPAGESIZE 0x1000
+#define elf_backend_size_info mips_elf64_size_info
+#define elf_backend_object_p _bfd_mips_elf_object_p
+#define elf_backend_section_from_shdr mips_elf64_section_from_shdr
+#define elf_backend_fake_sections _bfd_mips_elf_fake_sections
+#define elf_backend_section_from_bfd_section \
+ _bfd_mips_elf_section_from_bfd_section
+#define elf_backend_section_processing mips_elf64_section_processing
+#define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
+#define elf_backend_final_write_processing \
+ _bfd_mips_elf_final_write_processing
+#define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
+
+#define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
+#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
+#define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
+#define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
+#define bfd_elf64_bfd_copy_private_bfd_data \
+ _bfd_mips_elf_copy_private_bfd_data
+#define bfd_elf64_bfd_merge_private_bfd_data \
+ _bfd_mips_elf_merge_private_bfd_data
+#define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
+
+#include "elf64-target.h"
diff --git a/gnu/usr.bin/binutils/bfd/freebsd.h b/gnu/usr.bin/binutils/bfd/freebsd.h
new file mode 100644
index 00000000000..7e1d69d0df7
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/freebsd.h
@@ -0,0 +1,109 @@
+/* BFD back-end definitions used by all FreeBSD targets.
+ Copyright (C) 1990, 1991, 1992, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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.
+*/
+
+/* FreeBSD ZMAGIC files never have the header in the text. */
+#define N_HEADER_IN_TEXT(x) 0
+
+/* ZMAGIC files start at offset 0. Does not apply to QMAGIC files. */
+#define TEXT_START_ADDR 0
+
+#define N_GETMAGIC_NET(exec) \
+ (ntohl ((exec).a_info) & 0xffff)
+#define N_GETMID_NET(exec) \
+ ((ntohl ((exec).a_info) >> 16) & 0x3ff)
+#define N_GETFLAG_NET(ex) \
+ ((ntohl ((exec).a_info) >> 26) & 0x3f)
+
+#define N_MACHTYPE(exec) \
+ ((enum machine_type) \
+ ((N_GETMAGIC_NET (exec) == ZMAGIC) ? N_GETMID_NET (exec) : \
+ ((exec).a_info >> 16) & 0x3ff))
+#define N_FLAGS(exec) \
+ ((N_GETMAGIC_NET (exec) == ZMAGIC) ? N_GETFLAG_NET (exec) : \
+ ((exec).a_info >> 26) & 0x3f)
+
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0x3ff) << 16) \
+ | (((flags) & 0x3f) << 26))
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_info = \
+ ((exec).a_info & 0xfb00ffff) | ((((int)(machtype))&0x3ff) << 16))
+#define N_SET_FLAGS(exec, flags) \
+ ((exec).a_info = \
+ ((exec).a_info & 0x03ffffff) | ((flags & 0x03f) << 26))
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h"
+
+/* On FreeBSD, the magic number is always in correct endian format */
+#define NO_SWAP_MAGIC
+
+
+#define MY_write_object_contents MY(write_object_contents)
+static boolean MY(write_object_contents) PARAMS ((bfd *abfd));
+
+#include "aout-target.h"
+
+/* Write an object file.
+ Section contents have already been written. We write the
+ file header, symbols, and relocation. */
+
+static boolean
+MY(write_object_contents) (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+#if CHOOSE_RELOC_SIZE
+ CHOOSE_RELOC_SIZE(abfd);
+#else
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+#endif
+
+ /* Magic number, maestro, please! */
+ switch (bfd_get_arch(abfd)) {
+ case bfd_arch_m68k:
+ if (strcmp (abfd->xvec->name, "a.out-m68k4k-netbsd") == 0)
+ N_SET_MACHTYPE(*execp, M_68K4K_NETBSD);
+ else
+ N_SET_MACHTYPE(*execp, M_68K_NETBSD);
+ break;
+ case bfd_arch_sparc:
+ N_SET_MACHTYPE(*execp, M_SPARC_NETBSD);
+ break;
+ case bfd_arch_i386:
+ N_SET_MACHTYPE(*execp, M_386_NETBSD);
+ break;
+ case bfd_arch_ns32k:
+ N_SET_MACHTYPE(*execp, M_532_NETBSD);
+ break;
+ default:
+ N_SET_MACHTYPE(*execp, M_UNKNOWN);
+ break;
+ }
+
+ WRITE_HEADERS(abfd, execp);
+
+ return true;
+}
diff --git a/gnu/usr.bin/binutils/bfd/hosts/m68kaux.h b/gnu/usr.bin/binutils/bfd/hosts/m68kaux.h
new file mode 100644
index 00000000000..6237755dba5
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/hosts/m68kaux.h
@@ -0,0 +1,16 @@
+/* Definitions for an Apple Macintosh running A/UX 3.x. */
+
+#include <sys/param.h>
+#include <sys/page.h>
+
+/* Definitions used by trad-core.c. */
+#define NBPG NBPP
+
+#define HOST_DATA_START_ADDR u.u_exdata.ux_datorg
+#define HOST_TEXT_START_ADDR u.u_exdata.ux_txtorg
+#define HOST_STACK_END_ADDR 0x100000000
+
+#define UPAGES USIZE
+
+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(abfd) \
+ (abfd->tdata.trad_core_data->u.u_arg[0])
diff --git a/gnu/usr.bin/binutils/bfd/hosts/m68klinux.h b/gnu/usr.bin/binutils/bfd/hosts/m68klinux.h
new file mode 100644
index 00000000000..0067dfa6fda
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/hosts/m68klinux.h
@@ -0,0 +1,6 @@
+/* Linux dumps "struct task_struct" at the end of the core-file. This
+ structure is currently 2512 bytes long, but we allow up to 4096
+ bytes to allow for some future growth. */
+#define TRAD_CORE_EXTRA_SIZE_ALLOWED 4096
+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(abfd) \
+ ((abfd)->tdata.trad_core_data->u.signal)
diff --git a/gnu/usr.bin/binutils/bfd/i386freebsd.c b/gnu/usr.bin/binutils/bfd/i386freebsd.c
new file mode 100644
index 00000000000..7a6371b5df6
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/i386freebsd.c
@@ -0,0 +1,33 @@
+/* BFD back-end for FreeBSD/386 a.out-ish binaries.
+ Copyright (C) 1990, 1991, 1992, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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. */
+
+#define BYTES_IN_WORD 4
+#undef TARGET_IS_BIG_ENDIAN_P
+
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+
+#define DEFAULT_ARCH bfd_arch_i386
+#define MACHTYPE_OK(mtype) ((mtype) == M_386_NETBSD || (mtype) == M_UNKNOWN)
+
+#define MY(OP) CAT(i386freebsd_,OP)
+/* This needs to start with a.out so GDB knows it is an a.out variant. */
+#define TARGETNAME "a.out-i386-freebsd"
+
+#include "freebsd.h"
diff --git a/gnu/usr.bin/binutils/bfd/ihex.c b/gnu/usr.bin/binutils/bfd/ihex.c
new file mode 100644
index 00000000000..abe61c676c2
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/ihex.c
@@ -0,0 +1,1023 @@
+/* BFD back-end for Intel Hex objects.
+ Copyright 1995 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor of Cygnus Support <ian@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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. */
+
+/* This is what Intel Hex files look like:
+
+1. INTEL FORMATS
+
+A. Intel 1
+
+ 16-bit address-field format, for files 64k bytes in length or less.
+
+ DATA RECORD
+ Byte 1 Header = colon(:)
+ 2..3 The number of data bytes in hex notation
+ 4..5 High byte of the record load address
+ 6..7 Low byte of the record load address
+ 8..9 Record type, must be "00"
+ 10..x Data bytes in hex notation:
+ x = (number of bytes - 1) * 2 + 11
+ x+1..x+2 Checksum in hex notation
+ x+3..x+4 Carriage return, line feed
+
+ END RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count, must be "00"
+ 4..7 Transfer-address (usually "0000")
+ the jump-to address, execution start address
+ 8..9 Record type, must be "01"
+ 10..11 Checksum, in hex notation
+ 12..13 Carriage return, line feed
+
+B. INTEL 2
+
+ MCS-86 format, using a 20-bit address for files larger than 64K bytes.
+
+ DATA RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count of this record, hex notation
+ 4..5 High byte of the record load address
+ 6..7 Low byte of the record load address
+ 8..9 Record type, must be "00"
+ 10..x The data bytes in hex notation:
+ x = (number of data bytes - 1) * 2 + 11
+ x+1..x+2 Checksum in hex notation
+ x+3..x+4 Carriage return, line feed
+
+ EXTENDED ADDRESS RECORD
+ Byte 1 Header = colon(:)
+ 2..3 The byte count, must be "02"
+ 4..7 Load address, must be "0000"
+ 8..9 Record type, must be "02"
+ 10..11 High byte of the offset address
+ 12..13 Low byte of the offset address
+ 14..15 Checksum in hex notation
+ 16..17 Carriage return, line feed
+
+ The checksums are the two's complement of the 8-bit sum
+ without carry of the byte count, offset address, and the
+ record type.
+
+ START ADDRESS RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count, must be "04"
+ 4..7 Load address, must be "0000"
+ 8..9 Record type, must be "03"
+ 10..13 8086 CS value
+ 14..17 8086 IP value
+ 18..19 Checksum in hex notation
+ 20..21 Carriage return, line feed
+
+Another document reports these additional types:
+
+ EXTENDED LINEAR ADDRESS RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count, must be "02"
+ 4..7 Load address, must be "0000"
+ 8..9 Record type, must be "04"
+ 10..13 Upper 16 bits of address of subsequent records
+ 14..15 Checksum in hex notation
+ 16..17 Carriage return, line feed
+
+ START LINEAR ADDRESS RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count, must be "02"
+ 4..7 Load address, must be "0000"
+ 8..9 Record type, must be "05"
+ 10..13 Upper 16 bits of start address
+ 14..15 Checksum in hex notation
+ 16..17 Carriage return, line feed
+
+The MRI compiler uses this, which is a repeat of type 5:
+
+ EXTENDED START RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count, must be "04"
+ 4..7 Load address, must be "0000"
+ 8..9 Record type, must be "05"
+ 10..13 Upper 16 bits of start address
+ 14..17 Lower 16 bits of start address
+ 18..19 Checksum in hex notation
+ 20..21 Carriage return, line feed
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libiberty.h"
+
+#include <ctype.h>
+
+static void ihex_init PARAMS ((void));
+static boolean ihex_mkobject PARAMS ((bfd *));
+static INLINE int ihex_get_byte PARAMS ((bfd *, boolean *));
+static void ihex_bad_byte PARAMS ((bfd *, unsigned int, int, boolean));
+static boolean ihex_scan PARAMS ((bfd *));
+static const bfd_target *ihex_object_p PARAMS ((bfd *));
+static boolean ihex_read_section PARAMS ((bfd *, asection *, bfd_byte *));
+static boolean ihex_get_section_contents
+ PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+static boolean ihex_set_section_contents
+ PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+static boolean ihex_write_record
+ PARAMS ((bfd *, bfd_size_type, bfd_vma, unsigned int, bfd_byte *));
+static boolean ihex_write_object_contents PARAMS ((bfd *));
+static asymbol *ihex_make_empty_symbol PARAMS ((bfd *));
+static boolean ihex_set_arch_mach
+ PARAMS ((bfd *, enum bfd_architecture, unsigned long));
+
+/* The number of bytes we put on one line during output. */
+
+#define CHUNK (21)
+
+/* Macros for converting between hex and binary. */
+
+#define NIBBLE(x) (hex_value (x))
+#define HEX2(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
+#define HEX4(buffer) ((HEX2 (buffer) << 8) + HEX2 ((buffer) + 2))
+#define ISHEX(x) (hex_p (x))
+
+/* When we write out an ihex value, the values can not be output as
+ they are seen. Instead, we hold them in memory in this structure. */
+
+struct ihex_data_list
+{
+ struct ihex_data_list *next;
+ bfd_byte *data;
+ bfd_vma where;
+ bfd_size_type size;
+};
+
+/* The ihex tdata information. */
+
+struct ihex_data_struct
+{
+ struct ihex_data_list *head;
+ struct ihex_data_list *tail;
+};
+
+/* Initialize by filling in the hex conversion array. */
+
+static void
+ihex_init ()
+{
+ static boolean inited;
+
+ if (! inited)
+ {
+ inited = true;
+ hex_init ();
+ }
+}
+
+/* Create an ihex object. */
+
+static boolean
+ihex_mkobject (abfd)
+ bfd *abfd;
+{
+ if (abfd->tdata.ihex_data == NULL)
+ {
+ struct ihex_data_struct *tdata;
+
+ tdata = ((struct ihex_data_struct *)
+ bfd_alloc (abfd, sizeof (struct ihex_data_struct)));
+ if (tdata == NULL)
+ return false;
+ abfd->tdata.ihex_data = tdata;
+ tdata->head = NULL;
+ tdata->tail = NULL;
+ }
+
+ return true;
+}
+
+/* Read a byte from a BFD. Set *ERRORPTR if an error occurred.
+ Return EOF on error or end of file. */
+
+static INLINE int
+ihex_get_byte (abfd, errorptr)
+ bfd *abfd;
+ boolean *errorptr;
+{
+ bfd_byte c;
+
+ if (bfd_read (&c, 1, 1, abfd) != 1)
+ {
+ if (bfd_get_error () != bfd_error_file_truncated)
+ *errorptr = true;
+ return EOF;
+ }
+
+ return (int) (c & 0xff);
+}
+
+/* Report a problem in an Intel Hex file. */
+
+static void
+ihex_bad_byte (abfd, lineno, c, error)
+ bfd *abfd;
+ unsigned int lineno;
+ int c;
+ boolean error;
+{
+ if (c == EOF)
+ {
+ if (! error)
+ bfd_set_error (bfd_error_file_truncated);
+ }
+ else
+ {
+ char buf[10];
+
+ if (! isprint (c))
+ sprintf (buf, "\\%03o", (unsigned int) c);
+ else
+ {
+ buf[0] = c;
+ buf[1] = '\0';
+ }
+ (*_bfd_error_handler)
+ ("%s:%d: unexpected character `%s' in Intel Hex file\n",
+ bfd_get_filename (abfd), lineno, buf);
+ bfd_set_error (bfd_error_bad_value);
+ }
+}
+
+/* Read an Intel hex file and turn it into sections. We create a new
+ section for each contiguous set of bytes. */
+
+static boolean
+ihex_scan (abfd)
+ bfd *abfd;
+{
+ bfd_vma segbase;
+ bfd_vma extbase;
+ asection *sec;
+ int lineno;
+ boolean error;
+ bfd_byte *buf;
+ size_t bufsize;
+ int c;
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ goto error_return;
+
+ abfd->start_address = 0;
+
+ extbase = 0;
+ segbase = 0;
+ sec = NULL;
+ lineno = 1;
+ error = false;
+ buf = NULL;
+ bufsize = 0;
+ while ((c = ihex_get_byte (abfd, &error)) != EOF)
+ {
+ if (c == '\r')
+ continue;
+ else if (c == '\n')
+ {
+ ++lineno;
+ continue;
+ }
+ else if (c != ':')
+ {
+ ihex_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+ else
+ {
+ file_ptr pos;
+ char hdr[8];
+ unsigned int i;
+ unsigned int len;
+ bfd_vma addr;
+ unsigned int type;
+ unsigned int chars;
+ unsigned int chksum;
+
+ /* This is a data record. */
+
+ pos = bfd_tell (abfd) - 1;
+
+ /* Read the header bytes. */
+
+ if (bfd_read (hdr, 1, 8, abfd) != 8)
+ goto error_return;
+
+ for (i = 0; i < 8; i++)
+ {
+ if (! ISHEX (hdr[i]))
+ {
+ ihex_bad_byte (abfd, lineno, hdr[i], error);
+ goto error_return;
+ }
+ }
+
+ len = HEX2 (hdr);
+ addr = HEX4 (hdr + 2);
+ type = HEX2 (hdr + 6);
+
+ /* Read the data bytes. */
+
+ chars = len * 2 + 2;
+ if (chars >= bufsize)
+ {
+ buf = (bfd_byte *) bfd_realloc (buf, chars);
+ if (buf == NULL)
+ goto error_return;
+ bufsize = chars;
+ }
+
+ if (bfd_read (buf, 1, chars, abfd) != chars)
+ goto error_return;
+
+ for (i = 0; i < chars; i++)
+ {
+ if (! ISHEX (buf[i]))
+ {
+ ihex_bad_byte (abfd, lineno, hdr[i], error);
+ goto error_return;
+ }
+ }
+
+ /* Check the checksum. */
+ chksum = len + addr + (addr >> 8) + type;
+ for (i = 0; i < len; i++)
+ chksum += HEX2 (buf + 2 * i);
+ if (((- chksum) & 0xff) != (unsigned int) HEX2 (buf + 2 * i))
+ {
+ (*_bfd_error_handler)
+ ("%s:%d: bad checksum in Intel Hex file (expected %u, found %u)",
+ bfd_get_filename (abfd), lineno,
+ (- chksum) & 0xff, (unsigned int) HEX2 (buf + 2 * i));
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ switch (type)
+ {
+ case 0:
+ /* This is a data record. */
+ if (sec != NULL
+ && sec->vma + sec->_raw_size == extbase + segbase + addr)
+ {
+ /* This data goes at the end of the section we are
+ currently building. */
+ sec->_raw_size += len;
+ }
+ else if (len > 0)
+ {
+ char secbuf[20];
+ char *secname;
+
+ sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
+ secname = (char *) bfd_alloc (abfd, strlen (secbuf) + 1);
+ if (secname == NULL)
+ goto error_return;
+ strcpy (secname, secbuf);
+ sec = bfd_make_section (abfd, secname);
+ if (sec == NULL)
+ goto error_return;
+ sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
+ sec->vma = extbase + segbase + addr;
+ sec->lma = extbase + segbase + addr;
+ sec->_raw_size = len;
+ sec->filepos = pos;
+ }
+ break;
+
+ case 1:
+ /* An end record. */
+ if (abfd->start_address == 0)
+ abfd->start_address = addr;
+ if (buf != NULL)
+ free (buf);
+ return true;
+
+ case 2:
+ /* An extended address record. */
+ if (len != 2)
+ {
+ (*_bfd_error_handler)
+ ("%s:%d: bad extended address record length in Intel Hex file",
+ bfd_get_filename (abfd), lineno);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ segbase = HEX4 (buf) << 4;
+
+ sec = NULL;
+
+ break;
+
+ case 3:
+ /* An extended start address record. */
+ if (len != 4)
+ {
+ (*_bfd_error_handler)
+ ("%s:%d: bad extended start address length in Intel Hex file",
+ bfd_get_filename (abfd), lineno);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ abfd->start_address += (HEX4 (buf) << 4) + HEX4 (buf + 4);
+
+ sec = NULL;
+
+ break;
+
+ case 4:
+ /* An extended linear address record. */
+ if (len != 2)
+ {
+ (*_bfd_error_handler)
+ ("%s:%d: bad extended linear address record length in Intel Hex file",
+ bfd_get_filename (abfd), lineno);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ segbase = HEX4 (buf) << 16;
+
+ sec = NULL;
+
+ break;
+
+ case 5:
+ /* An extended linear start address record. */
+ if (len != 2 && len != 4)
+ {
+ (*_bfd_error_handler)
+ ("%s:%d: bad extended linear start address length in Intel Hex file",
+ bfd_get_filename (abfd), lineno);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ if (len == 2)
+ abfd->start_address += HEX4 (buf) << 16;
+ else
+ abfd->start_address = (HEX4 (buf) << 16) + HEX4 (buf + 4);
+
+ sec = NULL;
+
+ break;
+
+ default:
+ (*_bfd_error_handler)
+ ("%s:%d: unrecognized ihex type %u in Intel Hex file\n",
+ bfd_get_filename (abfd), lineno, type);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+ }
+ }
+
+ if (error)
+ goto error_return;
+
+ if (buf != NULL)
+ free (buf);
+
+ return true;
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ return false;
+}
+
+/* Try to recognize an Intel Hex file. */
+
+static const bfd_target *
+ihex_object_p (abfd)
+ bfd *abfd;
+{
+ bfd_byte b[9];
+ unsigned int i;
+ unsigned int type;
+
+ ihex_init ();
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ return NULL;
+ if (bfd_read (b, 1, 9, abfd) != 9)
+ {
+ if (bfd_get_error () == bfd_error_file_truncated)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if (b[0] != ':')
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ for (i = 1; i < 9; i++)
+ {
+ if (! ISHEX (b[i]))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+ }
+
+ type = HEX2 (b + 7);
+ if (type > 5)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* OK, it looks like it really is an Intel Hex file. */
+
+ if (! ihex_mkobject (abfd)
+ || ! ihex_scan (abfd))
+ return NULL;
+
+ return abfd->xvec;
+}
+
+/* Read the contents of a section in an Intel Hex file. */
+
+static boolean
+ihex_read_section (abfd, section, contents)
+ bfd *abfd;
+ asection *section;
+ bfd_byte *contents;
+{
+ int c;
+ bfd_byte *p;
+ bfd_byte *buf;
+ size_t bufsize;
+ boolean error;
+
+ if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
+ goto error_return;
+
+ p = contents;
+ buf = NULL;
+ bufsize = 0;
+ error = false;
+ while ((c = ihex_get_byte (abfd, &error)) != EOF)
+ {
+ char hdr[8];
+ unsigned int len;
+ bfd_vma addr;
+ unsigned int type;
+ unsigned int i;
+
+ if (c == '\r' || c == '\n')
+ continue;
+
+ /* This is called after ihex_scan has succeeded, so we ought to
+ know the exact format. */
+ BFD_ASSERT (c == ':');
+
+ if (bfd_read (hdr, 1, 8, abfd) != 8)
+ goto error_return;
+
+ len = HEX2 (hdr);
+ addr = HEX4 (hdr + 2);
+ type = HEX2 (hdr + 6);
+
+ /* We should only see type 0 records here. */
+ if (type != 0)
+ {
+ (*_bfd_error_handler)
+ ("%s: internal error in ihex_read_section",
+ bfd_get_filename (abfd));
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ if (len * 2 > bufsize)
+ {
+ buf = (bfd_byte *) bfd_realloc (buf, len * 2);
+ if (buf == NULL)
+ goto error_return;
+ bufsize = len * 2;
+ }
+
+ if (bfd_read (buf, 1, len * 2, abfd) != len * 2)
+ goto error_return;
+
+ for (i = 0; i < len; i++)
+ *p++ = HEX2 (buf + 2 * i);
+ if ((bfd_size_type) (p - contents) >= section->_raw_size)
+ {
+ /* We've read everything in the section. */
+ if (buf != NULL)
+ free (buf);
+ return true;
+ }
+
+ /* Skip the checksum. */
+ if (bfd_read (buf, 1, 2, abfd) != 2)
+ goto error_return;
+ }
+
+ if ((bfd_size_type) (p - contents) < section->_raw_size)
+ {
+ (*_bfd_error_handler)
+ ("%s: bad section length in ihex_read_section",
+ bfd_get_filename (abfd));
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ if (buf != NULL)
+ free (buf);
+
+ return true;
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ return false;
+}
+
+/* Get the contents of a section in an Intel Hex file. */
+
+static boolean
+ihex_get_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ if (section->used_by_bfd == NULL)
+ {
+ section->used_by_bfd = bfd_alloc (abfd, section->_raw_size);
+ if (section->used_by_bfd == NULL)
+ return false;
+ if (! ihex_read_section (abfd, section, section->used_by_bfd))
+ return false;
+ }
+
+ memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
+ (size_t) count);
+
+ return true;
+}
+
+/* Set the contents of a section in an Intel Hex file. */
+
+static boolean
+ihex_set_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ struct ihex_data_list *n;
+ bfd_byte *data;
+ struct ihex_data_struct *tdata;
+
+ if (count == 0
+ || (section->flags & SEC_ALLOC) == 0
+ || (section->flags & SEC_LOAD) == 0)
+ return true;
+
+ n = ((struct ihex_data_list *)
+ bfd_alloc (abfd, sizeof (struct ihex_data_list)));
+ if (n == NULL)
+ return false;
+
+ data = (bfd_byte *) bfd_alloc (abfd, count);
+ if (data == NULL)
+ return false;
+ memcpy (data, location, (size_t) count);
+
+ n->data = data;
+ n->where = section->lma + offset;
+ n->size = count;
+
+ /* Sort the records by address. Optimize for the common case of
+ adding a record to the end of the list. */
+ tdata = abfd->tdata.ihex_data;
+ if (tdata->tail != NULL
+ && n->where >= tdata->tail->where)
+ {
+ tdata->tail->next = n;
+ n->next = NULL;
+ tdata->tail = n;
+ }
+ else
+ {
+ register struct ihex_data_list **pp;
+
+ for (pp = &tdata->head;
+ *pp != NULL && (*pp)->where < n->where;
+ pp = &(*pp)->next)
+ ;
+ n->next = *pp;
+ *pp = n;
+ if (n->next == NULL)
+ tdata->tail = n;
+ }
+
+ return true;
+}
+
+/* Write a record out to an Intel Hex file. */
+
+static boolean
+ihex_write_record (abfd, count, addr, type, data)
+ bfd *abfd;
+ bfd_size_type count;
+ bfd_vma addr;
+ unsigned int type;
+ bfd_byte *data;
+{
+ static const char digs[] = "0123456789ABCDEF";
+ char buf[9 + CHUNK * 2 + 4];
+ char *p;
+ unsigned int chksum;
+ unsigned int i;
+
+#define TOHEX(buf, v) \
+ ((buf)[0] = digs[((v) >> 4) & 0xf], (buf)[1] = digs[(v) & 0xf])
+
+ buf[0] = ':';
+ TOHEX (buf + 1, count);
+ TOHEX (buf + 3, (addr >> 8) & 0xff);
+ TOHEX (buf + 5, addr & 0xff);
+ TOHEX (buf + 7, type);
+
+ chksum = count + addr + (addr >> 8) + type;
+
+ for (i = 0, p = buf + 9; i < count; i++, p += 2, data++)
+ {
+ TOHEX (p, *data);
+ chksum += *data;
+ }
+
+ TOHEX (p, (- chksum) & 0xff);
+ p[2] = '\r';
+ p[3] = '\n';
+
+ if (bfd_write (buf, 1, 9 + count * 2 + 4, abfd) != 9 + count * 2 + 4)
+ return false;
+
+ return true;
+}
+
+/* Write out an Intel Hex file. */
+
+static boolean
+ihex_write_object_contents (abfd)
+ bfd *abfd;
+{
+ bfd_vma extbase;
+ bfd_vma segbase;
+ struct ihex_data_list *l;
+
+ extbase = 0;
+ segbase = 0;
+ for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next)
+ {
+ bfd_vma where;
+ bfd_byte *p;
+ bfd_size_type count;
+
+ where = l->where;
+ p = l->data;
+ count = l->size;
+ while (count > 0)
+ {
+ bfd_size_type now;
+
+ now = count;
+ if (now > CHUNK)
+ now = CHUNK;
+
+ if (where > extbase + segbase + 0xffff)
+ {
+ bfd_byte addr[2];
+
+ /* We need a new base address. */
+ if (where <= 0xfffff)
+ {
+ segbase = where & 0xf0000;
+ addr[0] = (segbase >> 12) & 0xff;
+ addr[1] = (segbase >> 4) & 0xff;
+ if (! ihex_write_record (abfd, 2, 0, 2, addr))
+ return false;
+ }
+ else
+ {
+ extbase = where & 0xffff0000;
+ if (where > extbase + 0xffff)
+ {
+ char buf[20];
+
+ sprintf_vma (buf, where);
+ (*_bfd_error_handler)
+ ("%s: address 0x%s out of range for Intex Hex file",
+ bfd_get_filename (abfd), buf);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ addr[0] = (extbase >> 24) & 0xff;
+ addr[1] = (extbase >> 16) & 0xff;
+ if (! ihex_write_record (abfd, 2, 0, 4, addr))
+ return false;
+ }
+ }
+
+ if (! ihex_write_record (abfd, now, where - (extbase + segbase),
+ 0, p))
+ return false;
+
+ where += now;
+ p += now;
+ count -= now;
+ }
+ }
+
+ if (abfd->start_address != 0)
+ {
+ bfd_vma start;
+ bfd_byte startbuf[4];
+
+ start = abfd->start_address;
+
+ if (start <= 0xfffff)
+ {
+ startbuf[0] = ((start & 0xf0000) >> 12) & 0xff;
+ startbuf[1] = 0;
+ startbuf[2] = (start >> 8) & 0xff;
+ startbuf[3] = start & 0xff;
+ if (! ihex_write_record (abfd, 4, 0, 3, startbuf))
+ return false;
+ }
+ else
+ {
+ startbuf[0] = (start >> 24) & 0xff;
+ startbuf[1] = (start >> 16) & 0xff;
+ startbuf[2] = (start >> 8) & 0xff;
+ startbuf[3] = start & 0xff;
+ if (! ihex_write_record (abfd, 4, 0, 5, startbuf))
+ return false;
+ }
+ }
+
+ if (! ihex_write_record (abfd, 0, 0, 1, NULL))
+ return false;
+
+ return true;
+}
+
+/* Make an empty symbol. This is required only because
+ bfd_make_section_anyway wants to create a symbol for the section. */
+
+static asymbol *
+ihex_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ asymbol *new;
+
+ new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
+ if (new != NULL)
+ new->the_bfd = abfd;
+ return new;
+}
+
+/* Set the architecture for the output file. The architecture is
+ irrelevant, so we ignore errors about unknown architectures. */
+
+static boolean
+ihex_set_arch_mach (abfd, arch, mach)
+ bfd *abfd;
+ enum bfd_architecture arch;
+ unsigned long mach;
+{
+ if (! bfd_default_set_arch_mach (abfd, arch, mach))
+ {
+ if (arch != bfd_arch_unknown)
+ return false;
+ }
+ return true;
+}
+
+/* Get the size of the headers, for the linker. */
+
+/*ARGSUSED*/
+static int
+ihex_sizeof_headers (abfd, exec)
+ bfd *abfd;
+ boolean exec;
+{
+ return 0;
+}
+
+/* Some random definitions for the target vector. */
+
+#define ihex_close_and_cleanup _bfd_generic_close_and_cleanup
+#define ihex_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define ihex_new_section_hook _bfd_generic_new_section_hook
+#define ihex_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+#define ihex_get_symtab_upper_bound bfd_0l
+#define ihex_get_symtab \
+ ((long (*) PARAMS ((bfd *, asymbol **))) bfd_0l)
+#define ihex_print_symbol _bfd_nosymbols_print_symbol
+#define ihex_get_symbol_info _bfd_nosymbols_get_symbol_info
+#define ihex_bfd_is_local_label _bfd_nosymbols_bfd_is_local_label
+#define ihex_get_lineno _bfd_nosymbols_get_lineno
+#define ihex_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define ihex_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define ihex_read_minisymbols _bfd_nosymbols_read_minisymbols
+#define ihex_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
+
+#define ihex_get_reloc_upper_bound \
+ ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
+#define ihex_canonicalize_reloc \
+ ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
+#define ihex_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+#define ihex_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define ihex_bfd_relax_section bfd_generic_relax_section
+#define ihex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define ihex_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define ihex_bfd_final_link _bfd_generic_final_link
+#define ihex_bfd_link_split_section _bfd_generic_link_split_section
+
+/* The Intel Hex target vector. */
+
+const bfd_target ihex_vec =
+{
+ "ihex", /* name */
+ bfd_target_ihex_flavour,
+ BFD_ENDIAN_UNKNOWN, /* target byte order */
+ BFD_ENDIAN_UNKNOWN, /* target headers byte order */
+ 0, /* object flags */
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD), /* section flags */
+ 0, /* leading underscore */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
+
+ {
+ _bfd_dummy_target,
+ ihex_object_p, /* bfd_check_format */
+ _bfd_dummy_target,
+ _bfd_dummy_target,
+ },
+ {
+ bfd_false,
+ ihex_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false,
+ },
+ { /* bfd_write_contents */
+ bfd_false,
+ ihex_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false,
+ },
+
+ BFD_JUMP_TABLE_GENERIC (ihex),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (ihex),
+ BFD_JUMP_TABLE_RELOCS (ihex),
+ BFD_JUMP_TABLE_WRITE (ihex),
+ BFD_JUMP_TABLE_LINK (ihex),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
diff --git a/gnu/usr.bin/binutils/bfd/m68klinux.c b/gnu/usr.bin/binutils/bfd/m68klinux.c
new file mode 100644
index 00000000000..062165b399b
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/m68klinux.c
@@ -0,0 +1,767 @@
+/* BFD back-end for linux flavored m68k a.out binaries.
+ Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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. */
+
+#define TARGET_PAGE_SIZE 4096
+#define ZMAGIC_DISK_BLOCK_SIZE 1024
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define TEXT_START_ADDR 0x0
+#define N_SHARED_LIB(x) 0
+#define BYTES_IN_WORD 4
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#define TARGET_IS_BIG_ENDIAN_P
+#define DEFAULT_ARCH bfd_arch_m68k
+#define MY(OP) CAT(m68klinux_,OP)
+#define TARGETNAME "a.out-m68k-linux"
+
+extern const bfd_target MY(vec);
+
+/* We always generate QMAGIC files in preference to ZMAGIC files. It
+ would be possible to make this a linker option, if that ever
+ becomes important. */
+
+static void MY_final_link_callback
+ PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
+
+static boolean
+m68klinux_bfd_final_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ obj_aout_subformat (abfd) = q_magic_format;
+ return NAME(aout,final_link) (abfd, info, MY_final_link_callback);
+}
+
+#define MY_bfd_final_link m68klinux_bfd_final_link
+
+/* Set the machine type correctly. */
+
+static boolean
+m68klinux_write_object_contents (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+ N_SET_MACHTYPE (*execp, M_68020);
+
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+
+ WRITE_HEADERS(abfd, execp);
+
+ return true;
+}
+
+#define MY_write_object_contents m68klinux_write_object_contents
+
+/* Code to link against Linux a.out shared libraries. */
+
+/* See if a symbol name is a reference to the global offset table. */
+
+#ifndef GOT_REF_PREFIX
+#define GOT_REF_PREFIX "__GOT_"
+#endif
+
+#define IS_GOT_SYM(name) \
+ (strncmp (name, GOT_REF_PREFIX, sizeof GOT_REF_PREFIX - 1) == 0)
+
+/* See if a symbol name is a reference to the procedure linkage table. */
+
+#ifndef PLT_REF_PREFIX
+#define PLT_REF_PREFIX "__PLT_"
+#endif
+
+#define IS_PLT_SYM(name) \
+ (strncmp (name, PLT_REF_PREFIX, sizeof PLT_REF_PREFIX - 1) == 0)
+
+/* This string is used to generate specialized error messages. */
+
+#ifndef NEEDS_SHRLIB
+#define NEEDS_SHRLIB "__NEEDS_SHRLIB_"
+#endif
+
+/* This special symbol is a set vector that contains a list of
+ pointers to fixup tables. It will be present in any dynamicly
+ linked file. The linker generated fixup table should also be added
+ to the list, and it should always appear in the second slot (the
+ first one is a dummy with a magic number that is defined in
+ crt0.o). */
+
+#ifndef SHARABLE_CONFLICTS
+#define SHARABLE_CONFLICTS "__SHARABLE_CONFLICTS__"
+#endif
+
+/* We keep a list of fixups. The terminology is a bit strange, but
+ each fixup contains two 32 bit numbers. A regular fixup contains
+ an address and a pointer, and at runtime we should store the
+ address at the location pointed to by the pointer. A builtin fixup
+ contains two pointers, and we should read the address using one
+ pointer and store it at the location pointed to by the other
+ pointer. Builtin fixups come into play when we have duplicate
+ __GOT__ symbols for the same variable. The builtin fixup will copy
+ the GOT pointer from one over into the other. */
+
+struct fixup
+{
+ struct fixup *next;
+ struct linux_link_hash_entry *h;
+ bfd_vma value;
+
+ /* Nonzero if this is a jump instruction that needs to be fixed,
+ zero if this is just a pointer */
+ char jump;
+
+ char builtin;
+};
+
+/* We don't need a special hash table entry structure, but we do need
+ to keep some information between linker passes, so we use a special
+ hash table. */
+
+struct linux_link_hash_entry
+{
+ struct aout_link_hash_entry root;
+};
+
+struct linux_link_hash_table
+{
+ struct aout_link_hash_table root;
+
+ /* First dynamic object found in link. */
+ bfd *dynobj;
+
+ /* Number of fixups. */
+ size_t fixup_count;
+
+ /* Number of builtin fixups. */
+ size_t local_builtins;
+
+ /* List of fixups. */
+ struct fixup *fixup_list;
+};
+
+static struct bfd_hash_entry *linux_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static struct bfd_link_hash_table *linux_link_hash_table_create
+ PARAMS ((bfd *));
+static struct fixup *new_fixup
+ PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *,
+ bfd_vma, int));
+static boolean linux_link_create_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean linux_add_one_symbol
+ PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
+ bfd_vma, const char *, boolean, boolean,
+ struct bfd_link_hash_entry **));
+static boolean linux_tally_symbols
+ PARAMS ((struct linux_link_hash_entry *, PTR));
+static boolean linux_finish_dynamic_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Routine to create an entry in an Linux link hash table. */
+
+static struct bfd_hash_entry *
+linux_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct linux_link_hash_entry *ret = (struct linux_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct linux_link_hash_entry *) NULL)
+ ret = ((struct linux_link_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct linux_link_hash_entry)));
+ if (ret == NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct linux_link_hash_entry *)
+ NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
+ table, string));
+ if (ret != NULL)
+ {
+ /* Set local fields; there aren't any. */
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create a Linux link hash table. */
+
+static struct bfd_link_hash_table *
+linux_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct linux_link_hash_table *ret;
+
+ ret = ((struct linux_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct linux_link_hash_table)));
+ if (ret == (struct linux_link_hash_table *) NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+ if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
+ linux_link_hash_newfunc))
+ {
+ free (ret);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+
+ ret->dynobj = NULL;
+ ret->fixup_count = 0;
+ ret->local_builtins = 0;
+ ret->fixup_list = NULL;
+
+ return &ret->root.root;
+}
+
+/* Look up an entry in a Linux link hash table. */
+
+#define linux_link_hash_lookup(table, string, create, copy, follow) \
+ ((struct linux_link_hash_entry *) \
+ aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
+ (follow)))
+
+/* Traverse a Linux link hash table. */
+
+#define linux_link_hash_traverse(table, func, info) \
+ (aout_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the Linux link hash table from the info structure. This is
+ just a cast. */
+
+#define linux_hash_table(p) ((struct linux_link_hash_table *) ((p)->hash))
+
+/* Store the information for a new fixup. */
+
+static struct fixup *
+new_fixup (info, h, value, builtin)
+ struct bfd_link_info *info;
+ struct linux_link_hash_entry *h;
+ bfd_vma value;
+ int builtin;
+{
+ struct fixup *f;
+
+ f = (struct fixup *) bfd_hash_allocate (&info->hash->table,
+ sizeof (struct fixup));
+ if (f == NULL)
+ return f;
+ f->next = linux_hash_table (info)->fixup_list;
+ linux_hash_table (info)->fixup_list = f;
+ f->h = h;
+ f->value = value;
+ f->builtin = builtin;
+ f->jump = 0;
+ ++linux_hash_table (info)->fixup_count;
+ return f;
+}
+
+/* We come here once we realize that we are going to link to a shared
+ library. We need to create a special section that contains the
+ fixup table, and we ultimately need to add a pointer to this into
+ the set vector for SHARABLE_CONFLICTS. At this point we do not
+ know the size of the section, but that's OK - we just need to
+ create it for now. */
+
+static boolean
+linux_link_create_dynamic_sections (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ flagword flags;
+ register asection *s;
+
+ /* Note that we set the SEC_IN_MEMORY flag. */
+ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+
+ /* We choose to use the name ".linux-dynamic" for the fixup table.
+ Why not? */
+ s = bfd_make_section (abfd, ".linux-dynamic");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+ s->_raw_size = 0;
+ s->contents = 0;
+
+ return true;
+}
+
+/* Function to add a single symbol to the linker hash table. This is
+ a wrapper around _bfd_generic_link_add_one_symbol which handles the
+ tweaking needed for dynamic linking support. */
+
+static boolean
+linux_add_one_symbol (info, abfd, name, flags, section, value, string,
+ copy, collect, hashp)
+ struct bfd_link_info *info;
+ bfd *abfd;
+ const char *name;
+ flagword flags;
+ asection *section;
+ bfd_vma value;
+ const char *string;
+ boolean copy;
+ boolean collect;
+ struct bfd_link_hash_entry **hashp;
+{
+ struct linux_link_hash_entry *h;
+ boolean insert;
+
+ /* Look up and see if we already have this symbol in the hash table.
+ If we do, and the defining entry is from a shared library, we
+ need to create the dynamic sections.
+
+ FIXME: What if abfd->xvec != info->hash->creator? We may want to
+ be able to link Linux a.out and ELF objects together, but serious
+ confusion is possible. */
+
+ insert = false;
+
+ if (! info->relocateable
+ && linux_hash_table (info)->dynobj == NULL
+ && strcmp (name, SHARABLE_CONFLICTS) == 0
+ && (flags & BSF_CONSTRUCTOR) != 0
+ && abfd->xvec == info->hash->creator)
+ {
+ if (! linux_link_create_dynamic_sections (abfd, info))
+ return false;
+ linux_hash_table (info)->dynobj = abfd;
+ insert = true;
+ }
+
+ if (bfd_is_abs_section (section)
+ && abfd->xvec == info->hash->creator)
+ {
+ h = linux_link_hash_lookup (linux_hash_table (info), name, false,
+ false, false);
+ if (h != NULL
+ && (h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak))
+ {
+ struct fixup *f;
+
+ if (hashp != NULL)
+ *hashp = (struct bfd_link_hash_entry *) h;
+
+ f = new_fixup (info, h, value, ! IS_PLT_SYM (name));
+ if (f == NULL)
+ return false;
+ f->jump = IS_PLT_SYM (name);
+
+ return true;
+ }
+ }
+
+ /* Do the usual procedure for adding a symbol. */
+ if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
+ value, string, copy, collect,
+ hashp))
+ return false;
+
+ /* Insert a pointer to our table in the set vector. The dynamic
+ linker requires this information */
+ if (insert)
+ {
+ asection *s;
+
+ /* Here we do our special thing to add the pointer to the
+ dynamic section in the SHARABLE_CONFLICTS set vector. */
+ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
+ ".linux-dynamic");
+ BFD_ASSERT (s != NULL);
+
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS,
+ BSF_GLOBAL | BSF_CONSTRUCTOR, s, 0, NULL, false, false, NULL)))
+ return false;
+ }
+
+ return true;
+}
+
+/* We will crawl the hash table and come here for every global symbol.
+ We will examine each entry and see if there are indications that we
+ need to add a fixup. There are two possible cases - one is where
+ you have duplicate definitions of PLT or GOT symbols - these will
+ have already been caught and added as "builtin" fixups. If we find
+ that the corresponding non PLT/GOT symbol is also present, we
+ convert it to a regular fixup instead.
+
+ This function is called via linux_link_hash_traverse. */
+
+static boolean
+linux_tally_symbols (h, data)
+ struct linux_link_hash_entry *h;
+ PTR data;
+{
+ struct bfd_link_info *info = (struct bfd_link_info *) data;
+ struct fixup *f, *f1;
+ int is_plt;
+ struct linux_link_hash_entry *h1, *h2;
+ boolean exists;
+
+ if (h->root.root.type == bfd_link_hash_undefined
+ && strncmp (h->root.root.root.string, NEEDS_SHRLIB,
+ sizeof NEEDS_SHRLIB - 1) == 0)
+ {
+ const char *name;
+ char *p;
+ char *alloc = NULL;
+
+ name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1;
+ p = strrchr (name, '_');
+ if (p != NULL)
+ alloc = (char *) bfd_malloc (strlen (name) + 1);
+
+ if (p == NULL || alloc == NULL)
+ (*_bfd_error_handler) ("Output file requires shared library `%s'\n",
+ name);
+ else
+ {
+ strcpy (alloc, name);
+ p = strrchr (alloc, '_');
+ *p++ = '\0';
+ (*_bfd_error_handler)
+ ("Output file requires shared library `%s.so.%s'\n",
+ alloc, p);
+ free (alloc);
+ }
+
+ abort ();
+ }
+
+ /* If this symbol is not a PLT/GOT, we do not even need to look at it */
+ is_plt = IS_PLT_SYM (h->root.root.root.string);
+
+ if (is_plt || IS_GOT_SYM (h->root.root.root.string))
+ {
+ /* Look up this symbol twice. Once just as a regular lookup,
+ and then again following all of the indirect links until we
+ reach a real symbol. */
+ h1 = linux_link_hash_lookup (linux_hash_table (info),
+ (h->root.root.root.string
+ + sizeof PLT_REF_PREFIX - 1),
+ false, false, true);
+ /* h2 does not follow indirect symbols. */
+ h2 = linux_link_hash_lookup (linux_hash_table (info),
+ (h->root.root.root.string
+ + sizeof PLT_REF_PREFIX - 1),
+ false, false, false);
+
+ /* The real symbol must exist but if it is also an ABS symbol,
+ there is no need to have a fixup. This is because they both
+ came from the same library. If on the other hand, we had to
+ use an indirect symbol to get to the real symbol, we add the
+ fixup anyway, since there are cases where these symbols come
+ from different shared libraries */
+ if (h1 != NULL
+ && (((h1->root.root.type == bfd_link_hash_defined
+ || h1->root.root.type == bfd_link_hash_defweak)
+ && ! bfd_is_abs_section (h1->root.root.u.def.section))
+ || h2->root.root.type == bfd_link_hash_indirect))
+ {
+ /* See if there is a "builtin" fixup already present
+ involving this symbol. If so, convert it to a regular
+ fixup. In the end, this relaxes some of the requirements
+ about the order of performing fixups. */
+ exists = false;
+ for (f1 = linux_hash_table (info)->fixup_list;
+ f1 != NULL;
+ f1 = f1->next)
+ {
+ if ((f1->h != h && f1->h != h1)
+ || (! f1->builtin && ! f1->jump))
+ continue;
+ if (f1->h == h1)
+ exists = true;
+ if (! exists
+ && bfd_is_abs_section (h->root.root.u.def.section))
+ {
+ f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0);
+ f->jump = is_plt;
+ }
+ f1->h = h1;
+ f1->jump = is_plt;
+ f1->builtin = 0;
+ exists = true;
+ }
+ if (! exists
+ && bfd_is_abs_section (h->root.root.u.def.section))
+ {
+ f = new_fixup (info, h1, h->root.root.u.def.value, 0);
+ if (f == NULL)
+ {
+ /* FIXME: No way to return error. */
+ abort ();
+ }
+ f->jump = is_plt;
+ }
+ }
+
+ /* Quick and dirty way of stripping these symbols from the
+ symtab. */
+ if (bfd_is_abs_section (h->root.root.u.def.section))
+ h->root.written = true;
+ }
+
+ return true;
+}
+
+/* This is called to set the size of the .linux-dynamic section is.
+ It is called by the Linux linker emulation before_allocation
+ routine. We have finished reading all of the input files, and now
+ we just scan the hash tables to find out how many additional fixups
+ are required. */
+
+boolean
+bfd_m68klinux_size_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ struct fixup *f;
+ asection *s;
+
+ if (output_bfd->xvec != &MY(vec))
+ return true;
+
+ /* First find the fixups... */
+ linux_link_hash_traverse (linux_hash_table (info),
+ linux_tally_symbols,
+ (PTR) info);
+
+ /* If there are builtin fixups, leave room for a marker. This is
+ used by the dynamic linker so that it knows that all that follow
+ are builtin fixups instead of regular fixups. */
+ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
+ {
+ if (f->builtin)
+ {
+ ++linux_hash_table (info)->fixup_count;
+ ++linux_hash_table (info)->local_builtins;
+ break;
+ }
+ }
+
+ if (linux_hash_table (info)->dynobj == NULL)
+ {
+ if (linux_hash_table (info)->fixup_count > 0)
+ abort ();
+ return true;
+ }
+
+ /* Allocate memory for our fixup table. We will fill it in later. */
+ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
+ ".linux-dynamic");
+ if (s != NULL)
+ {
+ s->_raw_size = 8 + linux_hash_table (info)->fixup_count * 8;
+ s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+ if (s->contents == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ memset (s->contents, 0, (size_t) s->_raw_size);
+ }
+
+ return true;
+}
+
+/* We come here once we are ready to actually write the fixup table to
+ the output file. Scan the fixup tables and so forth and generate
+ the stuff we need. */
+
+static boolean
+linux_finish_dynamic_link (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ asection *s, *os, *is;
+ bfd_byte *fixup_table;
+ struct linux_link_hash_entry *h;
+ struct fixup *f;
+ unsigned int new_addr;
+ int section_offset;
+ unsigned int fixups_written;
+
+ if (linux_hash_table (info)->dynobj == NULL)
+ return true;
+
+ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
+ ".linux-dynamic");
+ BFD_ASSERT (s != NULL);
+ os = s->output_section;
+ fixups_written = 0;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Fixup table file offset: %x VMA: %x\n",
+ os->filepos + s->output_offset,
+ os->vma + s->output_offset);
+#endif
+
+ fixup_table = s->contents;
+ bfd_put_32 (output_bfd, linux_hash_table (info)->fixup_count, fixup_table);
+ fixup_table += 4;
+
+ /* Fill in fixup table. */
+ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
+ {
+ if (f->builtin)
+ continue;
+
+ if (f->h->root.root.type != bfd_link_hash_defined
+ && f->h->root.root.type != bfd_link_hash_defweak)
+ {
+ (*_bfd_error_handler)
+ ("Symbol %s not defined for fixups\n",
+ f->h->root.root.root.string);
+ continue;
+ }
+
+ is = f->h->root.root.u.def.section;
+ section_offset = is->output_section->vma + is->output_offset;
+ new_addr = f->h->root.root.u.def.value + section_offset;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string,
+ new_addr, f->value);
+#endif
+
+ if (f->jump)
+ {
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, f->value + 2, fixup_table);
+ fixup_table += 4;
+ }
+ else
+ {
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, f->value, fixup_table);
+ fixup_table += 4;
+ }
+ ++fixups_written;
+ }
+
+ if (linux_hash_table (info)->local_builtins != 0)
+ {
+ /* Special marker so we know to switch to the other type of fixup */
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ ++fixups_written;
+ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
+ {
+ if (! f->builtin)
+ continue;
+
+ if (f->h->root.root.type != bfd_link_hash_defined
+ && f->h->root.root.type != bfd_link_hash_defweak)
+ {
+ (*_bfd_error_handler)
+ ("Symbol %s not defined for fixups\n",
+ f->h->root.root.root.string);
+ continue;
+ }
+
+ is = f->h->root.root.u.def.section;
+ section_offset = is->output_section->vma + is->output_offset;
+ new_addr = f->h->root.root.u.def.value + section_offset;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string,
+ new_addr, f->value);
+#endif
+
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, f->value, fixup_table);
+ fixup_table += 4;
+ ++fixups_written;
+ }
+ }
+
+ if (linux_hash_table (info)->fixup_count != fixups_written)
+ {
+ (*_bfd_error_handler) ("Warning: fixup count mismatch\n");
+ while (linux_hash_table (info)->fixup_count > fixups_written)
+ {
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ ++fixups_written;
+ }
+ }
+
+ h = linux_link_hash_lookup (linux_hash_table (info),
+ "__BUILTIN_FIXUPS__",
+ false, false, false);
+
+ if (h != NULL
+ && (h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak))
+ {
+ is = h->root.root.u.def.section;
+ section_offset = is->output_section->vma + is->output_offset;
+ new_addr = h->root.root.u.def.value + section_offset;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Builtin fixup table at %x\n", new_addr);
+#endif
+
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ }
+ else
+ bfd_put_32 (output_bfd, 0, fixup_table);
+
+ if (bfd_seek (output_bfd, os->filepos + s->output_offset, SEEK_SET) != 0)
+ return false;
+
+ if (bfd_write ((PTR) s->contents, 1, s->_raw_size, output_bfd)
+ != s->_raw_size)
+ return false;
+
+ return true;
+}
+
+#define MY_bfd_link_hash_table_create linux_link_hash_table_create
+#define MY_add_one_symbol linux_add_one_symbol
+#define MY_finish_dynamic_link linux_finish_dynamic_link
+
+#define MY_zmagic_contiguous 1
+
+#include "aout-target.h"
diff --git a/gnu/usr.bin/binutils/bfd/netbsd-core.c b/gnu/usr.bin/binutils/bfd/netbsd-core.c
new file mode 100644
index 00000000000..e11100d87b4
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/netbsd-core.c
@@ -0,0 +1,309 @@
+/* BFD back end for NetBSD style core files
+ Copyright 1988, 1989, 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
+ Written by Paul Kranenburg, EUR
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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 "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/core.h>
+#include <errno.h>
+
+/*
+ * FIXME: On NetBSD/sparc CORE_FPU_OFFSET should be (sizeof(struct trapframe))
+ */
+
+struct netbsd_core_struct {
+ struct core core;
+} *rawptr;
+
+/* forward declarations */
+
+static const bfd_target * netbsd_core_core_file_p PARAMS ((bfd *abfd));
+static char * netbsd_core_core_file_failing_command PARAMS ((bfd *abfd));
+static int netbsd_core_core_file_failing_signal PARAMS ((bfd *abfd));
+static boolean netbsd_core_core_file_matches_executable_p
+ PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+/* Handle NetBSD-style core dump file. */
+
+/* ARGSUSED */
+static const bfd_target *
+netbsd_core_core_file_p (abfd)
+ bfd *abfd;
+
+{
+ int i, val, offset;
+ asection *asect, *asect2;
+ struct core core;
+ struct coreseg coreseg;
+
+ val = bfd_read ((void *)&core, 1, sizeof core, abfd);
+ if (val != sizeof core) {
+ /* Too small to be a core file */
+ bfd_set_error(bfd_error_wrong_format);
+ return 0;
+ }
+
+ if (CORE_GETMAGIC(core) != COREMAGIC) {
+ bfd_set_error(bfd_error_wrong_format);
+ return 0;
+ }
+
+ rawptr = (struct netbsd_core_struct *)
+ bfd_zalloc (abfd, sizeof (struct netbsd_core_struct));
+ if (rawptr == NULL) {
+ bfd_set_error(bfd_error_no_memory);
+ return 0;
+ }
+
+ rawptr->core = core;
+ abfd->tdata.netbsd_core_data = rawptr;
+
+ offset = core.c_hdrsize;
+ for (i = 0; i < core.c_nseg; i++) {
+
+ if (bfd_seek (abfd, offset, SEEK_SET) != 0)
+ goto punt;
+
+ val = bfd_read ((void *)&coreseg, 1, sizeof coreseg, abfd);
+ if (val != sizeof coreseg) {
+ bfd_set_error(bfd_error_file_truncated);
+ goto punt;
+ }
+ if (CORE_GETMAGIC(coreseg) != CORESEGMAGIC) {
+ bfd_set_error(bfd_error_wrong_format);
+ goto punt;
+ }
+
+ offset += core.c_seghdrsize;
+
+ asect = (asection *) bfd_zalloc (abfd, sizeof(asection));
+ if (asect == NULL) {
+ bfd_set_error(bfd_error_no_memory);
+ }
+
+ asect->_raw_size = coreseg.c_size;
+ asect->vma = coreseg.c_addr;
+ asect->filepos = offset;
+ asect->alignment_power = 2;
+ asect->next = abfd->sections;
+ abfd->sections = asect;
+ abfd->section_count++;
+ offset += coreseg.c_size;
+
+ switch (CORE_GETFLAG(coreseg)) {
+ case CORE_CPU:
+ asect->name = ".reg";
+ asect->flags = SEC_ALLOC + SEC_HAS_CONTENTS;
+#ifdef CORE_FPU_OFFSET
+ /* Hackish... */
+ asect->_raw_size = CORE_FPU_OFFSET;
+ asect2 = (asection *)bfd_zalloc (abfd,
+ sizeof (asection));
+ if (asect2 == NULL) {
+ bfd_set_error(bfd_error_no_memory);
+ goto punt;
+ }
+ asect2->_raw_size = coreseg.c_size - CORE_FPU_OFFSET;
+ asect2->vma = 0;
+ asect2->filepos = asect->filepos + CORE_FPU_OFFSET;
+ asect2->alignment_power = 2;
+ asect2->next = abfd->sections;
+ asect2->name = ".reg2";
+ asect2->flags = SEC_ALLOC + SEC_HAS_CONTENTS;
+ abfd->sections = asect2;
+ abfd->section_count++;
+#endif
+
+ break;
+ case CORE_DATA:
+ asect->name = ".data";
+ asect->flags = SEC_ALLOC+SEC_LOAD+SEC_HAS_CONTENTS;
+ break;
+ case CORE_STACK:
+ asect->name = ".stack";
+ asect->flags = SEC_ALLOC+SEC_LOAD+SEC_HAS_CONTENTS;
+ break;
+ }
+ }
+
+ /* OK, we believe you. You're a core file (sure, sure). */
+ return abfd->xvec;
+
+punt: {
+ asection *anext;
+ for (asect = abfd->sections; asect; asect = anext) {
+ anext = asect->next;
+ free((void *)asect);
+ }
+ }
+ free ((void *)rawptr);
+ abfd->tdata.netbsd_core_data = NULL;
+ abfd->sections = NULL;
+ abfd->section_count = 0;
+ return 0;
+}
+
+static char*
+netbsd_core_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ /*return core_command (abfd);*/
+ return abfd->tdata.netbsd_core_data->core.c_name;
+}
+
+/* ARGSUSED */
+static int
+netbsd_core_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ /*return core_signal (abfd);*/
+ return abfd->tdata.netbsd_core_data->core.c_signo;
+}
+
+/* ARGSUSED */
+static boolean
+netbsd_core_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd, *exec_bfd;
+{
+ return true; /* FIXME, We have no way of telling at this point */
+}
+
+/* No archive file support via this BFD */
+#define netbsd_openr_next_archived_file bfd_generic_openr_next_archived_file
+#define netbsd_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#define netbsd_slurp_armap bfd_false
+#define netbsd_slurp_extended_name_table bfd_true
+#define netbsd_write_armap (boolean (*) PARAMS \
+ ((bfd *arch, unsigned int elength, struct orl *map, \
+ unsigned int orl_count, int stridx))) bfd_false
+#define netbsd_truncate_arname bfd_dont_truncate_arname
+#define aout_32_openr_next_archived_file bfd_generic_openr_next_archived_file
+
+#define netbsd_close_and_cleanup bfd_generic_close_and_cleanup
+#define netbsd_set_section_contents (boolean (*) PARAMS \
+ ((bfd *abfd, asection *section, PTR data, file_ptr offset, \
+ bfd_size_type count))) bfd_false
+#define netbsd_get_section_contents bfd_generic_get_section_contents
+#define netbsd_new_section_hook (boolean (*) PARAMS \
+ ((bfd *, sec_ptr))) bfd_true
+#define netbsd_get_symtab_upper_bound bfd_0u
+#define netbsd_get_symtab (unsigned int (*) PARAMS \
+ ((bfd *, struct symbol_cache_entry **))) bfd_0u
+#define netbsd_get_reloc_upper_bound (unsigned int (*) PARAMS \
+ ((bfd *, sec_ptr))) bfd_0u
+#define netbsd_canonicalize_reloc (unsigned int (*) PARAMS \
+ ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u
+#define netbsd_make_empty_symbol (struct symbol_cache_entry * \
+ (*) PARAMS ((bfd *))) bfd_false
+#define netbsd_print_symbol (void (*) PARAMS \
+ ((bfd *, PTR, struct symbol_cache_entry *, \
+ bfd_print_symbol_type))) bfd_false
+#define netbsd_get_symbol_info (void (*) PARAMS \
+ ((bfd *, struct symbol_cache_entry *, \
+ symbol_info *))) bfd_false
+#define netbsd_get_lineno (alent * (*) PARAMS \
+ ((bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr
+#define netbsd_set_arch_mach (boolean (*) PARAMS \
+ ((bfd *, enum bfd_architecture, unsigned long))) bfd_false
+#define netbsd_find_nearest_line (boolean (*) PARAMS \
+ ((bfd *abfd, struct sec *section, \
+ struct symbol_cache_entry **symbols,bfd_vma offset, \
+ CONST char **file, CONST char **func, unsigned int *line))) bfd_false
+#define netbsd_sizeof_headers (int (*) PARAMS \
+ ((bfd *, boolean))) bfd_0
+
+#define netbsd_bfd_debug_info_start bfd_void
+#define netbsd_bfd_debug_info_end bfd_void
+#define netbsd_bfd_debug_info_accumulate (void (*) PARAMS \
+ ((bfd *, struct sec *))) bfd_void
+#define netbsd_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
+#define netbsd_bfd_relax_section bfd_generic_relax_section
+#define netbsd_bfd_seclet_link \
+ ((boolean (*) PARAMS ((bfd *, PTR, boolean))) bfd_false)
+#define netbsd_bfd_reloc_type_lookup \
+ ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
+#define netbsd_bfd_make_debug_symbol \
+ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
+
+/* If somebody calls any byte-swapping routines, shoot them. */
+static void
+swap_abort()
+{
+ abort(); /* This way doesn't require any declaration for ANSI to fuck up */
+}
+#define NO_GET ((bfd_vma (*) PARAMS (( const bfd_byte *))) swap_abort )
+#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
+#define NO_SIGNED_GET \
+ ((bfd_signed_vma (*) PARAMS (( const bfd_byte *))) swap_abort )
+
+const bfd_target netbsd_core_vec =
+ {
+ "netbsd-core",
+ bfd_target_unknown_flavour,
+ true, /* target byte order */
+ true, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* symbol prefix */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ netbsd_core_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (netbsd_core),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
+ BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
+ BFD_JUMP_TABLE_WRITE (_bfd_generic),
+ BFD_JUMP_TABLE_LINK (_bfd_nolink),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0 /* backend_data */
+};
diff --git a/gnu/usr.bin/binutils/bfd/ns32k.h b/gnu/usr.bin/binutils/bfd/ns32k.h
new file mode 100644
index 00000000000..d63ba096219
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/ns32k.h
@@ -0,0 +1,41 @@
+/* Header file for ns32k routines.
+ Copyright 1996 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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. */
+
+extern bfd_reloc_status_type _bfd_ns32k_relocate_contents
+ PARAMS ((reloc_howto_type *, bfd *, bfd_vma, bfd_byte *));
+
+extern bfd_reloc_status_type _bfd_do_ns32k_reloc_contents
+ PARAMS ((reloc_howto_type *, bfd *, bfd_vma, bfd_byte *,
+ long (*) PARAMS ((bfd_byte *, long, long)),
+ int (*) PARAMS ((long, bfd_byte *, long, long))));
+
+extern bfd_reloc_status_type _bfd_ns32k_final_link_relocate
+ PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, bfd_vma,
+ bfd_vma, bfd_vma));
+
+extern long _bfd_ns32k_get_displacement PARAMS ((bfd_byte *, long, long));
+extern long _bfd_ns32k_get_immediate PARAMS ((bfd_byte *, long, long));
+extern int _bfd_ns32k_put_displacement PARAMS ((long, bfd_byte *, long, long));
+extern int _bfd_ns32k_put_immediate PARAMS ((long, bfd_byte *, long, long));
+
+extern bfd_reloc_status_type _bfd_ns32k_reloc_disp
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+extern bfd_reloc_status_type _bfd_ns32k_reloc_imm
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
diff --git a/gnu/usr.bin/binutils/bfd/ppcboot.c b/gnu/usr.bin/binutils/bfd/ppcboot.c
new file mode 100644
index 00000000000..03f98ddb175
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/ppcboot.c
@@ -0,0 +1,535 @@
+/* BFD back-end for PPCbug boot records.
+ Copyright 1996 Free Software Foundation, Inc.
+ Written by Michael Meissner, Cygnus Support, <meissner@cygnus.com>
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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. */
+
+/* This is a BFD backend which may be used to write PowerPCBug boot objects.
+ It may only be used for output, not input. The intention is that this may
+ be used as an output format for objcopy in order to generate raw binary
+ data.
+
+ This is very simple. The only complication is that the real data
+ will start at some address X, and in some cases we will not want to
+ include X zeroes just to get to that point. Since the start
+ address is not meaningful for this object file format, we use it
+ instead to indicate the number of zeroes to skip at the start of
+ the file. objcopy cooperates by specially setting the start
+ address to zero by default. */
+
+#include <ctype.h>
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/* PPCbug location structure */
+typedef struct ppcboot_location {
+ bfd_byte ind;
+ bfd_byte head;
+ bfd_byte sector;
+ bfd_byte cylinder;
+} ppcboot_location_t;
+
+/* PPCbug partition table layout */
+typedef struct ppcboot_partition {
+ ppcboot_location_t partition_begin; /* partition begin */
+ ppcboot_location_t partition_end; /* partition end */
+ bfd_byte sector_begin[4]; /* 32-bit start RBA (zero-based), little endian */
+ bfd_byte sector_length[4]; /* 32-bit RBA count (one-based), little endian */
+} ppcboot_partition_t;
+
+/* PPCbug boot layout. */
+typedef struct ppcboot_hdr {
+ bfd_byte pc_compatibility[446]; /* x86 instruction field */
+ ppcboot_partition_t partition[4]; /* partition information */
+ bfd_byte signature[2]; /* 0x55 and 0xaa */
+ bfd_byte entry_offset[4]; /* entry point offset, little endian */
+ bfd_byte length[4]; /* load image length, little endian */
+ bfd_byte flags; /* flag field */
+ bfd_byte os_id; /* OS_ID */
+ char partition_name[32]; /* partition name */
+ bfd_byte reserved1[470]; /* reserved */
+} ppcboot_hdr_t;
+
+/* Signature bytes for last 2 bytes of the 512 byte record */
+#define SIGNATURE0 0x55
+#define SIGNATURE1 0xaa
+
+/* PowerPC boot type */
+#define PPC_IND 0x41
+
+/* Information needed for ppcboot header */
+typedef struct ppcboot_data {
+ ppcboot_hdr_t header; /* raw header */
+ asection *sec; /* single section */
+} ppcboot_data_t;
+
+/* Any bfd we create by reading a ppcboot file has three symbols:
+ a start symbol, an end symbol, and an absolute length symbol. */
+#define PPCBOOT_SYMS 3
+
+static boolean ppcboot_mkobject PARAMS ((bfd *));
+static const bfd_target *ppcboot_object_p PARAMS ((bfd *));
+static boolean ppcboot_get_section_contents
+ PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+static long ppcboot_get_symtab_upper_bound PARAMS ((bfd *));
+static char *mangle_name PARAMS ((bfd *, char *));
+static long ppcboot_get_symtab PARAMS ((bfd *, asymbol **));
+static asymbol *ppcboot_make_empty_symbol PARAMS ((bfd *));
+static void ppcboot_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
+static boolean ppcboot_set_section_contents
+ PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+static int ppcboot_sizeof_headers PARAMS ((bfd *, boolean));
+
+#define ppcboot_set_tdata(abfd, ptr) ((abfd)->tdata.any = (PTR) (ptr))
+#define ppcboot_get_tdata(abfd) ((ppcboot_data_t *) ((abfd)->tdata.any))
+
+/* Create a ppcboot object. Invoked via bfd_set_format. */
+
+static boolean
+ppcboot_mkobject (abfd)
+ bfd *abfd;
+{
+ if (!ppcboot_get_tdata (abfd))
+ ppcboot_set_tdata (abfd, bfd_zalloc (abfd, sizeof (ppcboot_data_t)));
+
+ return true;
+}
+
+
+/* Set the architecture to PowerPC */
+boolean
+ppcboot_set_arch_mach (abfd, arch, machine)
+ bfd *abfd;
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ if (arch == bfd_arch_unknown)
+ arch = bfd_arch_powerpc;
+
+ else if (arch != bfd_arch_powerpc)
+ return false;
+
+ return bfd_default_set_arch_mach (abfd, arch, machine);
+}
+
+
+/* Any file may be considered to be a ppcboot file, provided the target
+ was not defaulted. That is, it must be explicitly specified as
+ being ppcboot. */
+
+static const bfd_target *
+ppcboot_object_p (abfd)
+ bfd *abfd;
+{
+ struct stat statbuf;
+ asection *sec;
+ ppcboot_hdr_t hdr;
+ int i;
+ ppcboot_data_t *tdata;
+
+ BFD_ASSERT (sizeof (ppcboot_hdr_t) == 1024);
+
+ if (abfd->target_defaulted)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* Find the file size. */
+ if (bfd_stat (abfd, &statbuf) < 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return NULL;
+ }
+
+ if (statbuf.st_size < sizeof (ppcboot_hdr_t))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if (bfd_read ((PTR) &hdr, sizeof (hdr), 1, abfd) != sizeof (hdr))
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+
+ return NULL;
+ }
+
+ /* Now do some basic checks. */
+ for (i = 0; i < sizeof (hdr.pc_compatibility); i++)
+ if (hdr.pc_compatibility[i])
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if (hdr.signature[0] != SIGNATURE0 || hdr.signature[1] != SIGNATURE1)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if (hdr.partition[0].partition_end.ind != PPC_IND)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ abfd->symcount = PPCBOOT_SYMS;
+
+ /* One data section. */
+ sec = bfd_make_section (abfd, ".data");
+ if (sec == NULL)
+ return NULL;
+ sec->flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_CODE | SEC_HAS_CONTENTS;
+ sec->vma = 0;
+ sec->_raw_size = statbuf.st_size - sizeof (ppcboot_hdr_t);
+ sec->filepos = sizeof (ppcboot_hdr_t);
+
+ ppcboot_mkobject (abfd);
+ tdata = ppcboot_get_tdata (abfd);
+ tdata->sec = sec;
+ memcpy ((PTR) &tdata->header, (PTR) &hdr, sizeof (ppcboot_hdr_t));
+
+ ppcboot_set_arch_mach (abfd, bfd_arch_powerpc, 0);
+ return abfd->xvec;
+}
+
+#define ppcboot_close_and_cleanup _bfd_generic_close_and_cleanup
+#define ppcboot_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define ppcboot_new_section_hook _bfd_generic_new_section_hook
+
+
+/* Get contents of the only section. */
+
+static boolean
+ppcboot_get_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ if (bfd_seek (abfd, offset + sizeof(ppcboot_hdr_t), SEEK_SET) != 0
+ || bfd_read (location, 1, count, abfd) != count)
+ return false;
+ return true;
+}
+
+
+/* Return the amount of memory needed to read the symbol table. */
+
+static long
+ppcboot_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ return (PPCBOOT_SYMS + 1) * sizeof (asymbol *);
+}
+
+
+/* Create a symbol name based on the bfd's filename. */
+
+static char *
+mangle_name (abfd, suffix)
+ bfd *abfd;
+ char *suffix;
+{
+ int size;
+ char *buf;
+ char *p;
+
+ size = (strlen (bfd_get_filename (abfd))
+ + strlen (suffix)
+ + sizeof "_ppcboot__");
+
+ buf = (char *) bfd_alloc (abfd, size);
+ if (buf == NULL)
+ return "";
+
+ sprintf (buf, "_ppcboot_%s_%s", bfd_get_filename (abfd), suffix);
+
+ /* Change any non-alphanumeric characters to underscores. */
+ for (p = buf; *p; p++)
+ if (! isalnum (*p))
+ *p = '_';
+
+ return buf;
+}
+
+
+/* Return the symbol table. */
+
+static long
+ppcboot_get_symtab (abfd, alocation)
+ bfd *abfd;
+ asymbol **alocation;
+{
+ asection *sec = ppcboot_get_tdata (abfd)->sec;
+ asymbol *syms;
+ unsigned int i;
+
+ syms = (asymbol *) bfd_alloc (abfd, PPCBOOT_SYMS * sizeof (asymbol));
+ if (syms == NULL)
+ return false;
+
+ /* Start symbol. */
+ syms[0].the_bfd = abfd;
+ syms[0].name = mangle_name (abfd, "start");
+ syms[0].value = 0;
+ syms[0].flags = BSF_GLOBAL;
+ syms[0].section = sec;
+ syms[0].udata.p = NULL;
+
+ /* End symbol. */
+ syms[1].the_bfd = abfd;
+ syms[1].name = mangle_name (abfd, "end");
+ syms[1].value = sec->_raw_size;
+ syms[1].flags = BSF_GLOBAL;
+ syms[1].section = sec;
+ syms[1].udata.p = NULL;
+
+ /* Size symbol. */
+ syms[2].the_bfd = abfd;
+ syms[2].name = mangle_name (abfd, "size");
+ syms[2].value = sec->_raw_size;
+ syms[2].flags = BSF_GLOBAL;
+ syms[2].section = bfd_abs_section_ptr;
+ syms[2].udata.p = NULL;
+
+ for (i = 0; i < PPCBOOT_SYMS; i++)
+ *alocation++ = syms++;
+ *alocation = NULL;
+
+ return PPCBOOT_SYMS;
+}
+
+
+/* Make an empty symbol. */
+
+static asymbol *
+ppcboot_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ return (asymbol *) bfd_alloc (abfd, sizeof (asymbol));
+}
+
+
+#define ppcboot_print_symbol _bfd_nosymbols_print_symbol
+
+/* Get information about a symbol. */
+
+static void
+ppcboot_get_symbol_info (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+#define ppcboot_bfd_is_local_label bfd_generic_is_local_label
+#define ppcboot_get_lineno _bfd_nosymbols_get_lineno
+#define ppcboot_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define ppcboot_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define ppcboot_read_minisymbols _bfd_generic_read_minisymbols
+#define ppcboot_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define ppcboot_get_reloc_upper_bound \
+ ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
+#define ppcboot_canonicalize_reloc \
+ ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
+#define ppcboot_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+/* Set the architecture of a ppcboot file. */
+#define ppcboot_set_arch_mach ppcboot_set_arch_mach
+
+
+/* Write section contents of a ppcboot file. */
+
+static boolean
+ppcboot_set_section_contents (abfd, sec, data, offset, size)
+ bfd *abfd;
+ asection *sec;
+ PTR data;
+ file_ptr offset;
+ bfd_size_type size;
+{
+ if (! abfd->output_has_begun)
+ {
+ bfd_vma low;
+ asection *s;
+
+ /* The lowest section VMA sets the virtual address of the start
+ of the file. We use the set the file position of all the
+ sections. */
+ low = abfd->sections->vma;
+ for (s = abfd->sections->next; s != NULL; s = s->next)
+ if (s->vma < low)
+ low = s->vma;
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ s->filepos = s->vma - low;
+
+ abfd->output_has_begun = true;
+ }
+
+ return _bfd_generic_set_section_contents (abfd, sec, data, offset, size);
+}
+
+
+static int
+ppcboot_sizeof_headers (abfd, exec)
+ bfd *abfd;
+ boolean exec;
+{
+ return sizeof (ppcboot_hdr_t);
+}
+
+
+/* Print out the program headers. */
+
+boolean
+ppcboot_bfd_print_private_bfd_data (abfd, farg)
+ bfd *abfd;
+ PTR farg;
+{
+ FILE *f = (FILE *)farg;
+ ppcboot_data_t *tdata = ppcboot_get_tdata (abfd);
+ long entry_offset = bfd_getl_signed_32 ((PTR) &tdata->header.entry_offset);
+ long length = bfd_getl_signed_32 ((PTR) &tdata->header.length);
+ int i;
+
+ fprintf (f, "\nppcboot header:\n");
+ fprintf (f, "Entry offset = 0x%.8lx (%ld)\n", entry_offset, entry_offset);
+ fprintf (f, "Length = 0x%.8lx (%ld)\n", length, length);
+
+ if (tdata->header.flags)
+ fprintf (f, "Flag field = 0x%.2x\n", tdata->header.flags);
+
+ if (tdata->header.os_id)
+ fprintf (f, "OS_ID = 0x%.2x\n", tdata->header.os_id);
+
+ if (tdata->header.partition_name)
+ fprintf (f, "Partition name = \"%s\"\n", tdata->header.partition_name);
+
+ for (i = 0; i < 4; i++)
+ {
+ long sector_begin = bfd_getl_signed_32 ((PTR) &tdata->header.partition[i].sector_begin);
+ long sector_length = bfd_getl_signed_32 ((PTR) &tdata->header.partition[i].sector_length);
+
+ /* Skip all 0 entries */
+ if (!tdata->header.partition[i].partition_begin.ind
+ && !tdata->header.partition[i].partition_begin.head
+ && !tdata->header.partition[i].partition_begin.sector
+ && !tdata->header.partition[i].partition_begin.cylinder
+ && !tdata->header.partition[i].partition_end.ind
+ && !tdata->header.partition[i].partition_end.head
+ && !tdata->header.partition[i].partition_end.sector
+ && !tdata->header.partition[i].partition_end.cylinder
+ && !sector_begin && !sector_length)
+ continue;
+
+ fprintf (f, "\nPartition[%d] start = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n", i,
+ tdata->header.partition[i].partition_begin.ind,
+ tdata->header.partition[i].partition_begin.head,
+ tdata->header.partition[i].partition_begin.sector,
+ tdata->header.partition[i].partition_begin.cylinder);
+
+ fprintf (f, "Partition[%d] end = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n", i,
+ tdata->header.partition[i].partition_end.ind,
+ tdata->header.partition[i].partition_end.head,
+ tdata->header.partition[i].partition_end.sector,
+ tdata->header.partition[i].partition_end.cylinder);
+
+ fprintf (f, "Partition[%d] sector = 0x%.8lx (%ld)\n", i, sector_begin, sector_begin);
+ fprintf (f, "Partition[%d] length = 0x%.8lx (%ld)\n", i, sector_length, sector_length);
+ }
+
+ fprintf (f, "\n");
+ return true;
+}
+
+
+#define ppcboot_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define ppcboot_bfd_relax_section bfd_generic_relax_section
+#define ppcboot_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define ppcboot_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define ppcboot_bfd_final_link _bfd_generic_final_link
+#define ppcboot_bfd_link_split_section _bfd_generic_link_split_section
+#define ppcboot_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+#define ppcboot_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data
+#define ppcboot_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
+#define ppcboot_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
+#define ppcboot_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
+#define ppcboot_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
+#define ppcboot_bfd_print_private_bfd_dat ppcboot_bfd_print_private_bfd_data
+
+const bfd_target ppcboot_vec =
+{
+ "ppcboot", /* name */
+ bfd_target_unknown_flavour, /* flavour */
+ BFD_ENDIAN_BIG, /* byteorder is big endian for code */
+ BFD_ENDIAN_LITTLE, /* header_byteorder */
+ EXEC_P, /* object_flags */
+ (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
+ | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
+ 0, /* symbol_leading_char */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
+ { /* bfd_check_format */
+ _bfd_dummy_target,
+ ppcboot_object_p, /* bfd_check_format */
+ _bfd_dummy_target,
+ _bfd_dummy_target,
+ },
+ { /* bfd_set_format */
+ bfd_false,
+ ppcboot_mkobject,
+ bfd_false,
+ bfd_false,
+ },
+ { /* bfd_write_contents */
+ bfd_false,
+ bfd_true,
+ bfd_false,
+ bfd_false,
+ },
+
+ BFD_JUMP_TABLE_GENERIC (ppcboot),
+ BFD_JUMP_TABLE_COPY (ppcboot),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (ppcboot),
+ BFD_JUMP_TABLE_RELOCS (ppcboot),
+ BFD_JUMP_TABLE_WRITE (ppcboot),
+ BFD_JUMP_TABLE_LINK (ppcboot),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ NULL
+};
diff --git a/gnu/usr.bin/binutils/bfd/stabs.c b/gnu/usr.bin/binutils/bfd/stabs.c
new file mode 100644
index 00000000000..26508976a59
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/stabs.c
@@ -0,0 +1,529 @@
+/* Stabs in sections linking support.
+ Copyright 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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. */
+
+/* This file contains support for linking stabs in sections, as used
+ on COFF and ELF. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "aout/stab_gnu.h"
+
+#include <ctype.h>
+
+/* Stabs entries use a 12 byte format:
+ 4 byte string table index
+ 1 byte stab type
+ 1 byte stab other field
+ 2 byte stab desc field
+ 4 byte stab value
+ FIXME: This will have to change for a 64 bit object format.
+
+ The stabs symbols are divided into compilation units. For the
+ first entry in each unit, the type of 0, the value is the length of
+ the string table for this unit, and the desc field is the number of
+ stabs symbols for this unit. */
+
+#define STRDXOFF (0)
+#define TYPEOFF (4)
+#define OTHEROFF (5)
+#define DESCOFF (6)
+#define VALOFF (8)
+#define STABSIZE (12)
+
+/* A hash table used for header files with N_BINCL entries. */
+
+struct stab_link_includes_table
+{
+ struct bfd_hash_table root;
+};
+
+/* A linked list of totals that we have found for a particular header
+ file. */
+
+struct stab_link_includes_totals
+{
+ struct stab_link_includes_totals *next;
+ bfd_vma total;
+};
+
+/* An entry in the header file hash table. */
+
+struct stab_link_includes_entry
+{
+ struct bfd_hash_entry root;
+ /* List of totals we have found for this file. */
+ struct stab_link_includes_totals *totals;
+};
+
+/* Look up an entry in an the header file hash table. */
+
+#define stab_link_includes_lookup(table, string, create, copy) \
+ ((struct stab_link_includes_entry *) \
+ bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
+
+/* This structure is used to hold a list of N_BINCL symbols, some of
+ which might be converted into N_EXCL symbols. */
+
+struct stab_excl_list
+{
+ /* The next symbol to convert. */
+ struct stab_excl_list *next;
+ /* The offset to this symbol in the section contents. */
+ bfd_size_type offset;
+ /* The value to use for the symbol. */
+ bfd_vma val;
+ /* The type of this symbol (N_BINCL or N_EXCL). */
+ int type;
+};
+
+/* This structure is stored with each .stab section. */
+
+struct stab_section_info
+{
+ /* This is a linked list of N_BINCL symbols which should be
+ converted into N_EXCL symbols. */
+ struct stab_excl_list *excls;
+ /* This is an array of string indices. For each stab symbol, we
+ store the string index here. If a stab symbol should not be
+ included in the final output, the string index is -1. */
+ bfd_size_type stridxs[1];
+};
+
+/* This structure is used to keep track of stabs in sections
+ information while linking. */
+
+struct stab_info
+{
+ /* A hash table used to hold stabs strings. */
+ struct bfd_strtab_hash *strings;
+ /* The header file hash table. */
+ struct stab_link_includes_table includes;
+ /* The first .stabstr section. */
+ asection *stabstr;
+};
+
+static struct bfd_hash_entry *stab_link_includes_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+
+/* The function to create a new entry in the header file hash table. */
+
+static struct bfd_hash_entry *
+stab_link_includes_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct stab_link_includes_entry *ret =
+ (struct stab_link_includes_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct stab_link_includes_entry *) NULL)
+ ret = ((struct stab_link_includes_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct stab_link_includes_entry)));
+ if (ret == (struct stab_link_includes_entry *) NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct stab_link_includes_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+ if (ret)
+ {
+ /* Set local fields. */
+ ret->totals = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* This function is called for each input file from the add_symbols
+ pass of the linker. */
+
+boolean
+_bfd_link_section_stabs (abfd, psinfo, stabsec, stabstrsec, psecinfo)
+ bfd *abfd;
+ PTR *psinfo;
+ asection *stabsec;
+ asection *stabstrsec;
+ PTR *psecinfo;
+{
+ struct stab_info *sinfo;
+ bfd_size_type count;
+ struct stab_section_info *secinfo;
+ bfd_byte *stabbuf = NULL;
+ bfd_byte *stabstrbuf = NULL;
+ bfd_byte *sym, *symend;
+ bfd_size_type stroff, next_stroff, skip;
+ bfd_size_type *pstridx;
+
+ if (stabsec->_raw_size == 0
+ || stabstrsec->_raw_size == 0)
+ {
+ /* This file does not contain stabs debugging information. */
+ return true;
+ }
+
+ if (stabsec->_raw_size % STABSIZE != 0)
+ {
+ /* Something is wrong with the format of these stab symbols.
+ Don't try to optimize them. */
+ return true;
+ }
+
+ if ((stabstrsec->flags & SEC_RELOC) != 0)
+ {
+ /* We shouldn't see relocations in the strings, and we aren't
+ prepared to handle them. */
+ return true;
+ }
+
+ if (*psinfo == NULL)
+ {
+ /* Initialize the stabs information we need to keep track of. */
+ *psinfo = ((struct stab_info *)
+ bfd_alloc (abfd, sizeof (struct stab_info)));
+ sinfo = *psinfo;
+ sinfo->strings = _bfd_stringtab_init ();
+ if (sinfo->strings == NULL)
+ goto error_return;
+ if (! bfd_hash_table_init_n (&sinfo->includes.root,
+ stab_link_includes_newfunc,
+ 251))
+ goto error_return;
+ sinfo->stabstr = bfd_make_section_anyway (abfd, ".stabstr");
+ sinfo->stabstr->flags |= SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING;
+ }
+
+ sinfo = (struct stab_info *) *psinfo;
+
+ /* Initialize the information we are going to store for this .stab
+ section. */
+
+ count = stabsec->_raw_size / STABSIZE;
+
+ *psecinfo = bfd_alloc (abfd,
+ (sizeof (struct stab_section_info)
+ + (count - 1) * sizeof (bfd_size_type)));
+ if (*psecinfo == NULL)
+ goto error_return;
+
+ secinfo = (struct stab_section_info *) *psecinfo;
+ secinfo->excls = NULL;
+ memset (secinfo->stridxs, 0, count * sizeof (bfd_size_type));
+
+ /* Read the stabs information from abfd. */
+
+ stabbuf = (bfd_byte *) bfd_malloc (stabsec->_raw_size);
+ stabstrbuf = (bfd_byte *) bfd_malloc (stabstrsec->_raw_size);
+ if (stabbuf == NULL || stabstrbuf == NULL)
+ goto error_return;
+
+ if (! bfd_get_section_contents (abfd, stabsec, stabbuf, 0,
+ stabsec->_raw_size)
+ || ! bfd_get_section_contents (abfd, stabstrsec, stabstrbuf, 0,
+ stabstrsec->_raw_size))
+ goto error_return;
+
+ /* Look through the stabs symbols, work out the new string indices,
+ and identify N_BINCL symbols which can be eliminated. */
+
+ stroff = 0;
+ next_stroff = 0;
+ skip = 0;
+
+ symend = stabbuf + stabsec->_raw_size;
+ for (sym = stabbuf, pstridx = secinfo->stridxs;
+ sym < symend;
+ sym += STABSIZE, ++pstridx)
+ {
+ int type;
+ const char *string;
+
+ if (*pstridx != 0)
+ {
+ /* This symbol has already been handled by an N_BINCL pass. */
+ continue;
+ }
+
+ type = sym[TYPEOFF];
+
+ if (type == 0)
+ {
+ /* Special type 0 stabs indicate the offset to the next
+ string table. We don't copy these into the output file. */
+ stroff = next_stroff;
+ next_stroff += bfd_get_32 (abfd, sym + 8);
+ *pstridx = (bfd_size_type) -1;
+ ++skip;
+ continue;
+ }
+
+ /* Store the string in the hash table, and record the index. */
+ string = ((char *) stabstrbuf
+ + stroff
+ + bfd_get_32 (abfd, sym + STRDXOFF));
+ *pstridx = _bfd_stringtab_add (sinfo->strings, string, true, true);
+
+ /* An N_BINCL symbol indicates the start of the stabs entries
+ for a header file. We need to scan ahead to the next N_EINCL
+ symbol, ignoring nesting, adding up all the characters in the
+ symbol names, not including the file numbers in types (the
+ first number after an open parenthesis). */
+ if (type == N_BINCL)
+ {
+ bfd_vma val;
+ int nest;
+ bfd_byte *incl_sym;
+ struct stab_link_includes_entry *incl_entry;
+ struct stab_link_includes_totals *t;
+ struct stab_excl_list *ne;
+
+ val = 0;
+ nest = 0;
+ for (incl_sym = sym + STABSIZE;
+ incl_sym < symend;
+ incl_sym += STABSIZE)
+ {
+ int incl_type;
+
+ incl_type = incl_sym[TYPEOFF];
+ if (incl_type == 0)
+ break;
+ else if (incl_type == N_EINCL)
+ {
+ if (nest == 0)
+ break;
+ --nest;
+ }
+ else if (incl_type == N_BINCL)
+ ++nest;
+ else if (nest == 0)
+ {
+ const char *str;
+
+ str = ((char *) stabstrbuf
+ + stroff
+ + bfd_get_32 (abfd, incl_sym + STRDXOFF));
+ for (; *str != '\0'; str++)
+ {
+ val += *str;
+ if (*str == '(')
+ {
+ /* Skip the file number. */
+ ++str;
+ while (isdigit ((unsigned char) *str))
+ ++str;
+ --str;
+ }
+ }
+ }
+ }
+
+ /* If we have already included a header file with the same
+ value, then replaced this one with an N_EXCL symbol. */
+ incl_entry = stab_link_includes_lookup (&sinfo->includes, string,
+ true, true);
+ if (incl_entry == NULL)
+ goto error_return;
+
+ for (t = incl_entry->totals; t != NULL; t = t->next)
+ if (t->total == val)
+ break;
+
+ /* Record this symbol, so that we can set the value
+ correctly. */
+ ne = (struct stab_excl_list *) bfd_alloc (abfd, sizeof *ne);
+ ne->offset = sym - stabbuf;
+ ne->val = val;
+ ne->type = N_BINCL;
+ ne->next = secinfo->excls;
+ secinfo->excls = ne;
+
+ if (t == NULL)
+ {
+ /* This is the first time we have seen this header file
+ with this set of stabs strings. */
+ t = ((struct stab_link_includes_totals *)
+ bfd_hash_allocate (&sinfo->includes.root, sizeof *t));
+ if (t == NULL)
+ goto error_return;
+ t->total = val;
+ t->next = incl_entry->totals;
+ incl_entry->totals = t;
+ }
+ else
+ {
+ bfd_size_type *incl_pstridx;
+
+ /* We have seen this header file before. Tell the final
+ pass to change the type to N_EXCL. */
+ ne->type = N_EXCL;
+
+ /* Mark the skipped symbols. */
+
+ nest = 0;
+ for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
+ incl_sym < symend;
+ incl_sym += STABSIZE, ++incl_pstridx)
+ {
+ int incl_type;
+
+ incl_type = incl_sym[TYPEOFF];
+
+ if (incl_type == N_EINCL)
+ {
+ if (nest == 0)
+ {
+ *incl_pstridx = (bfd_size_type) -1;
+ ++skip;
+ break;
+ }
+ --nest;
+ }
+ else if (incl_type == N_BINCL)
+ ++nest;
+ else if (nest == 0)
+ {
+ *incl_pstridx = (bfd_size_type) -1;
+ ++skip;
+ }
+ }
+ }
+ }
+ }
+
+ free (stabbuf);
+ free (stabstrbuf);
+
+ /* We need to set the section sizes such that the linker will
+ compute the output section sizes correctly. We set the .stab
+ size to not include the entries we don't want. We set
+ SEC_EXCLUDE for the .stabstr section, so that it will be dropped
+ from the link. We record the size of the strtab in the first
+ .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
+ for that section. */
+ stabsec->_cooked_size = (count - skip) * STABSIZE;
+ if (stabsec->_cooked_size == 0)
+ stabsec->flags |= SEC_EXCLUDE;
+ stabstrsec->flags |= SEC_EXCLUDE;
+ sinfo->stabstr->_cooked_size = _bfd_stringtab_size (sinfo->strings);
+
+ return true;
+
+ error_return:
+ if (stabbuf != NULL)
+ free (stabbuf);
+ if (stabstrbuf != NULL)
+ free (stabstrbuf);
+ return false;
+}
+
+/* Write out the stab section. This is called with the relocated
+ contents. */
+
+boolean
+_bfd_write_section_stabs (output_bfd, stabsec, psecinfo, contents)
+ bfd *output_bfd;
+ asection *stabsec;
+ PTR *psecinfo;
+ bfd_byte *contents;
+{
+ struct stab_section_info *secinfo;
+ struct stab_excl_list *e;
+ bfd_byte *sym, *tosym, *symend;
+ bfd_size_type *pstridx;
+
+ secinfo = (struct stab_section_info *) *psecinfo;
+
+ if (secinfo == NULL)
+ return bfd_set_section_contents (output_bfd, stabsec->output_section,
+ contents, stabsec->output_offset,
+ stabsec->_raw_size);
+
+ /* Handle each N_BINCL entry. */
+ for (e = secinfo->excls; e != NULL; e = e->next)
+ {
+ bfd_byte *excl_sym;
+
+ BFD_ASSERT (e->offset < stabsec->_raw_size);
+ excl_sym = contents + e->offset;
+ bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
+ excl_sym[TYPEOFF] = e->type;
+ }
+
+ /* Copy over all the stabs symbols, omitting the ones we don't want,
+ and correcting the string indices for those we do want. */
+ tosym = contents;
+ symend = contents + stabsec->_raw_size;
+ for (sym = contents, pstridx = secinfo->stridxs;
+ sym < symend;
+ sym += STABSIZE, ++pstridx)
+ {
+ if (*pstridx != (bfd_size_type) -1)
+ {
+ if (tosym != sym)
+ memcpy (tosym, sym, STABSIZE);
+ bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
+ tosym += STABSIZE;
+ }
+ }
+
+ BFD_ASSERT (tosym - contents == stabsec->_cooked_size);
+
+ return bfd_set_section_contents (output_bfd, stabsec->output_section,
+ contents, stabsec->output_offset,
+ stabsec->_cooked_size);
+}
+
+/* Write out the .stabstr section. */
+
+boolean
+_bfd_write_stab_strings (output_bfd, psinfo)
+ bfd *output_bfd;
+ PTR *psinfo;
+{
+ struct stab_info *sinfo;
+
+ sinfo = (struct stab_info *) *psinfo;
+
+ if (sinfo == NULL)
+ return true;
+
+ BFD_ASSERT ((sinfo->stabstr->output_offset
+ + _bfd_stringtab_size (sinfo->strings))
+ <= sinfo->stabstr->output_section->_raw_size);
+
+ if (bfd_seek (output_bfd,
+ (sinfo->stabstr->output_section->filepos
+ + sinfo->stabstr->output_offset),
+ SEEK_SET) != 0)
+ return false;
+
+ if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
+ return false;
+
+ /* We no longer need the stabs information. */
+ _bfd_stringtab_free (sinfo->strings);
+ bfd_hash_table_free (&sinfo->includes.root);
+
+ return true;
+}
diff --git a/gnu/usr.bin/binutils/binutils/budbg.h b/gnu/usr.bin/binutils/binutils/budbg.h
new file mode 100644
index 00000000000..d8ee8895e76
--- /dev/null
+++ b/gnu/usr.bin/binutils/binutils/budbg.h
@@ -0,0 +1,58 @@
+/* budbg.c -- Interfaces to the generic debugging information routines.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ 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. */
+
+#ifndef BUDBG_H
+#define BUDBG_H
+
+#include <stdio.h>
+
+/* Routine used to read generic debugging information. */
+
+extern PTR read_debugging_info PARAMS ((bfd *, asymbol **, long));
+
+/* Routine used to print generic debugging information. */
+
+extern boolean print_debugging_info PARAMS ((FILE *, PTR));
+
+/* Routines used to read and write stabs information. */
+
+extern PTR start_stab PARAMS ((PTR, bfd *, boolean, asymbol **, long));
+
+extern boolean finish_stab PARAMS ((PTR, PTR));
+
+extern boolean parse_stab PARAMS ((PTR, PTR, int, int, bfd_vma, const char *));
+
+extern boolean write_stabs_in_sections_debugging_info
+ PARAMS ((bfd *, PTR, bfd_byte **, bfd_size_type *, bfd_byte **,
+ bfd_size_type *));
+
+/* Routines used to read and write IEEE debugging information. */
+
+extern boolean parse_ieee
+ PARAMS ((PTR, bfd *, const bfd_byte *, bfd_size_type));
+
+extern boolean write_ieee_debugging_info PARAMS ((bfd *, PTR));
+
+/* Routine used to read COFF debugging information. */
+
+extern boolean parse_coff PARAMS ((bfd *, asymbol **, long, PTR));
+
+#endif
diff --git a/gnu/usr.bin/binutils/binutils/debug.c b/gnu/usr.bin/binutils/binutils/debug.c
new file mode 100644
index 00000000000..f508922edd8
--- /dev/null
+++ b/gnu/usr.bin/binutils/binutils/debug.c
@@ -0,0 +1,3501 @@
+/* debug.c -- Handle generic debugging information.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ 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. */
+
+/* This file implements a generic debugging format. We may eventually
+ have readers which convert different formats into this generic
+ format, and writers which write it out. The initial impetus for
+ this was writing a convertor from stabs to HP IEEE-695 debugging
+ format. */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "debug.h"
+
+/* Global information we keep for debugging. A pointer to this
+ structure is the debugging handle passed to all the routines. */
+
+struct debug_handle
+{
+ /* A linked list of compilation units. */
+ struct debug_unit *units;
+ /* The current compilation unit. */
+ struct debug_unit *current_unit;
+ /* The current source file. */
+ struct debug_file *current_file;
+ /* The current function. */
+ struct debug_function *current_function;
+ /* The current block. */
+ struct debug_block *current_block;
+ /* The current line number information for the current unit. */
+ struct debug_lineno *current_lineno;
+ /* Mark. This is used by debug_write. */
+ unsigned int mark;
+ /* A struct/class ID used by debug_write. */
+ unsigned int class_id;
+ /* The base for class_id for this call to debug_write. */
+ unsigned int base_id;
+ /* The current line number in debug_write. */
+ struct debug_lineno *current_write_lineno;
+ unsigned int current_write_lineno_index;
+ /* A list of classes which have assigned ID's during debug_write.
+ This is linked through the next_id field of debug_class_type. */
+ struct debug_class_id *id_list;
+ /* A list used to avoid recursion during debug_type_samep. */
+ struct debug_type_compare_list *compare_list;
+};
+
+/* Information we keep for a single compilation unit. */
+
+struct debug_unit
+{
+ /* The next compilation unit. */
+ struct debug_unit *next;
+ /* A list of files included in this compilation unit. The first
+ file is always the main one, and that is where the main file name
+ is stored. */
+ struct debug_file *files;
+ /* Line number information for this compilation unit. This is not
+ stored by function, because assembler code may have line number
+ information without function information. */
+ struct debug_lineno *linenos;
+};
+
+/* Information kept for a single source file. */
+
+struct debug_file
+{
+ /* The next source file in this compilation unit. */
+ struct debug_file *next;
+ /* The name of the source file. */
+ const char *filename;
+ /* Global functions, variables, types, etc. */
+ struct debug_namespace *globals;
+};
+
+/* A type. */
+
+struct debug_type
+{
+ /* Kind of type. */
+ enum debug_type_kind kind;
+ /* Size of type (0 if not known). */
+ unsigned int size;
+ /* Type which is a pointer to this type. */
+ debug_type pointer;
+ /* Tagged union with additional information about the type. */
+ union
+ {
+ /* DEBUG_KIND_INDIRECT. */
+ struct debug_indirect_type *kindirect;
+ /* DEBUG_KIND_INT. */
+ /* Whether the integer is unsigned. */
+ boolean kint;
+ /* DEBUG_KIND_STRUCT, DEBUG_KIND_UNION, DEBUG_KIND_CLASS,
+ DEBUG_KIND_UNION_CLASS. */
+ struct debug_class_type *kclass;
+ /* DEBUG_KIND_ENUM. */
+ struct debug_enum_type *kenum;
+ /* DEBUG_KIND_POINTER. */
+ struct debug_type *kpointer;
+ /* DEBUG_KIND_FUNCTION. */
+ struct debug_function_type *kfunction;
+ /* DEBUG_KIND_REFERENCE. */
+ struct debug_type *kreference;
+ /* DEBUG_KIND_RANGE. */
+ struct debug_range_type *krange;
+ /* DEBUG_KIND_ARRAY. */
+ struct debug_array_type *karray;
+ /* DEBUG_KIND_SET. */
+ struct debug_set_type *kset;
+ /* DEBUG_KIND_OFFSET. */
+ struct debug_offset_type *koffset;
+ /* DEBUG_KIND_METHOD. */
+ struct debug_method_type *kmethod;
+ /* DEBUG_KIND_CONST. */
+ struct debug_type *kconst;
+ /* DEBUG_KIND_VOLATILE. */
+ struct debug_type *kvolatile;
+ /* DEBUG_KIND_NAMED, DEBUG_KIND_TAGGED. */
+ struct debug_named_type *knamed;
+ } u;
+};
+
+/* Information kept for an indirect type. */
+
+struct debug_indirect_type
+{
+ /* Slot where the final type will appear. */
+ debug_type *slot;
+ /* Tag. */
+ const char *tag;
+};
+
+/* Information kept for a struct, union, or class. */
+
+struct debug_class_type
+{
+ /* NULL terminated array of fields. */
+ debug_field *fields;
+ /* A mark field which indicates whether the struct has already been
+ printed. */
+ unsigned int mark;
+ /* This is used to uniquely identify unnamed structs when printing. */
+ unsigned int id;
+ /* The remaining fields are only used for DEBUG_KIND_CLASS and
+ DEBUG_KIND_UNION_CLASS. */
+ /* NULL terminated array of base classes. */
+ debug_baseclass *baseclasses;
+ /* NULL terminated array of methods. */
+ debug_method *methods;
+ /* The type of the class providing the virtual function table for
+ this class. This may point to the type itself. */
+ debug_type vptrbase;
+};
+
+/* Information kept for an enum. */
+
+struct debug_enum_type
+{
+ /* NULL terminated array of names. */
+ const char **names;
+ /* Array of corresponding values. */
+ bfd_signed_vma *values;
+};
+
+/* Information kept for a function. FIXME: We should be able to
+ record the parameter types. */
+
+struct debug_function_type
+{
+ /* Return type. */
+ debug_type return_type;
+ /* NULL terminated array of argument types. */
+ debug_type *arg_types;
+ /* Whether the function takes a variable number of arguments. */
+ boolean varargs;
+};
+
+/* Information kept for a range. */
+
+struct debug_range_type
+{
+ /* Range base type. */
+ debug_type type;
+ /* Lower bound. */
+ bfd_signed_vma lower;
+ /* Upper bound. */
+ bfd_signed_vma upper;
+};
+
+/* Information kept for an array. */
+
+struct debug_array_type
+{
+ /* Element type. */
+ debug_type element_type;
+ /* Range type. */
+ debug_type range_type;
+ /* Lower bound. */
+ bfd_signed_vma lower;
+ /* Upper bound. */
+ bfd_signed_vma upper;
+ /* Whether this array is really a string. */
+ boolean stringp;
+};
+
+/* Information kept for a set. */
+
+struct debug_set_type
+{
+ /* Base type. */
+ debug_type type;
+ /* Whether this set is really a bitstring. */
+ boolean bitstringp;
+};
+
+/* Information kept for an offset type (a based pointer). */
+
+struct debug_offset_type
+{
+ /* The type the pointer is an offset from. */
+ debug_type base_type;
+ /* The type the pointer points to. */
+ debug_type target_type;
+};
+
+/* Information kept for a method type. */
+
+struct debug_method_type
+{
+ /* The return type. */
+ debug_type return_type;
+ /* The object type which this method is for. */
+ debug_type domain_type;
+ /* A NULL terminated array of argument types. */
+ debug_type *arg_types;
+ /* Whether the method takes a variable number of arguments. */
+ boolean varargs;
+};
+
+/* Information kept for a named type. */
+
+struct debug_named_type
+{
+ /* Name. */
+ struct debug_name *name;
+ /* Real type. */
+ debug_type type;
+};
+
+/* A field in a struct or union. */
+
+struct debug_field
+{
+ /* Name of the field. */
+ const char *name;
+ /* Type of the field. */
+ struct debug_type *type;
+ /* Visibility of the field. */
+ enum debug_visibility visibility;
+ /* Whether this is a static member. */
+ boolean static_member;
+ union
+ {
+ /* If static_member is false. */
+ struct
+ {
+ /* Bit position of the field in the struct. */
+ unsigned int bitpos;
+ /* Size of the field in bits. */
+ unsigned int bitsize;
+ } f;
+ /* If static_member is true. */
+ struct
+ {
+ const char *physname;
+ } s;
+ } u;
+};
+
+/* A base class for an object. */
+
+struct debug_baseclass
+{
+ /* Type of the base class. */
+ struct debug_type *type;
+ /* Bit position of the base class in the object. */
+ unsigned int bitpos;
+ /* Whether the base class is virtual. */
+ boolean virtual;
+ /* Visibility of the base class. */
+ enum debug_visibility visibility;
+};
+
+/* A method of an object. */
+
+struct debug_method
+{
+ /* The name of the method. */
+ const char *name;
+ /* A NULL terminated array of different types of variants. */
+ struct debug_method_variant **variants;
+};
+
+/* The variants of a method function of an object. These indicate
+ which method to run. */
+
+struct debug_method_variant
+{
+ /* The physical name of the function. */
+ const char *physname;
+ /* The type of the function. */
+ struct debug_type *type;
+ /* The visibility of the function. */
+ enum debug_visibility visibility;
+ /* Whether the function is const. */
+ boolean constp;
+ /* Whether the function is volatile. */
+ boolean volatilep;
+ /* The offset to the function in the virtual function table. */
+ bfd_vma voffset;
+ /* If voffset is VOFFSET_STATIC_METHOD, this is a static method. */
+#define VOFFSET_STATIC_METHOD ((bfd_vma) -1)
+ /* Context of a virtual method function. */
+ struct debug_type *context;
+};
+
+/* A variable. This is the information we keep for a variable object.
+ This has no name; a name is associated with a variable in a
+ debug_name structure. */
+
+struct debug_variable
+{
+ /* Kind of variable. */
+ enum debug_var_kind kind;
+ /* Type. */
+ debug_type type;
+ /* Value. The interpretation of the value depends upon kind. */
+ bfd_vma val;
+};
+
+/* A function. This has no name; a name is associated with a function
+ in a debug_name structure. */
+
+struct debug_function
+{
+ /* Return type. */
+ debug_type return_type;
+ /* Parameter information. */
+ struct debug_parameter *parameters;
+ /* Block information. The first structure on the list is the main
+ block of the function, and describes function local variables. */
+ struct debug_block *blocks;
+};
+
+/* A function parameter. */
+
+struct debug_parameter
+{
+ /* Next parameter. */
+ struct debug_parameter *next;
+ /* Name. */
+ const char *name;
+ /* Type. */
+ debug_type type;
+ /* Kind. */
+ enum debug_parm_kind kind;
+ /* Value (meaning depends upon kind). */
+ bfd_vma val;
+};
+
+/* A typed constant. */
+
+struct debug_typed_constant
+{
+ /* Type. */
+ debug_type type;
+ /* Value. FIXME: We may eventually need to support non-integral
+ values. */
+ bfd_vma val;
+};
+
+/* Information about a block within a function. */
+
+struct debug_block
+{
+ /* Next block with the same parent. */
+ struct debug_block *next;
+ /* Parent block. */
+ struct debug_block *parent;
+ /* List of child blocks. */
+ struct debug_block *children;
+ /* Start address of the block. */
+ bfd_vma start;
+ /* End address of the block. */
+ bfd_vma end;
+ /* Local variables. */
+ struct debug_namespace *locals;
+};
+
+/* Line number information we keep for a compilation unit. FIXME:
+ This structure is easy to create, but can be very space
+ inefficient. */
+
+struct debug_lineno
+{
+ /* More line number information for this block. */
+ struct debug_lineno *next;
+ /* Source file. */
+ struct debug_file *file;
+ /* Line numbers, terminated by a -1 or the end of the array. */
+#define DEBUG_LINENO_COUNT 10
+ unsigned long linenos[DEBUG_LINENO_COUNT];
+ /* Addresses for the line numbers. */
+ bfd_vma addrs[DEBUG_LINENO_COUNT];
+};
+
+/* A namespace. This is a mapping from names to objects. FIXME: This
+ should be implemented as a hash table. */
+
+struct debug_namespace
+{
+ /* List of items in this namespace. */
+ struct debug_name *list;
+ /* Pointer to where the next item in this namespace should go. */
+ struct debug_name **tail;
+};
+
+/* Kinds of objects that appear in a namespace. */
+
+enum debug_object_kind
+{
+ /* A type. */
+ DEBUG_OBJECT_TYPE,
+ /* A tagged type (really a different sort of namespace). */
+ DEBUG_OBJECT_TAG,
+ /* A variable. */
+ DEBUG_OBJECT_VARIABLE,
+ /* A function. */
+ DEBUG_OBJECT_FUNCTION,
+ /* An integer constant. */
+ DEBUG_OBJECT_INT_CONSTANT,
+ /* A floating point constant. */
+ DEBUG_OBJECT_FLOAT_CONSTANT,
+ /* A typed constant. */
+ DEBUG_OBJECT_TYPED_CONSTANT
+};
+
+/* Linkage of an object that appears in a namespace. */
+
+enum debug_object_linkage
+{
+ /* Local variable. */
+ DEBUG_LINKAGE_AUTOMATIC,
+ /* Static--either file static or function static, depending upon the
+ namespace is. */
+ DEBUG_LINKAGE_STATIC,
+ /* Global. */
+ DEBUG_LINKAGE_GLOBAL,
+ /* No linkage. */
+ DEBUG_LINKAGE_NONE
+};
+
+/* A name in a namespace. */
+
+struct debug_name
+{
+ /* Next name in this namespace. */
+ struct debug_name *next;
+ /* Name. */
+ const char *name;
+ /* Mark. This is used by debug_write. */
+ unsigned int mark;
+ /* Kind of object. */
+ enum debug_object_kind kind;
+ /* Linkage of object. */
+ enum debug_object_linkage linkage;
+ /* Tagged union with additional information about the object. */
+ union
+ {
+ /* DEBUG_OBJECT_TYPE. */
+ struct debug_type *type;
+ /* DEBUG_OBJECT_TAG. */
+ struct debug_type *tag;
+ /* DEBUG_OBJECT_VARIABLE. */
+ struct debug_variable *variable;
+ /* DEBUG_OBJECT_FUNCTION. */
+ struct debug_function *function;
+ /* DEBUG_OBJECT_INT_CONSTANT. */
+ bfd_vma int_constant;
+ /* DEBUG_OBJECT_FLOAT_CONSTANT. */
+ double float_constant;
+ /* DEBUG_OBJECT_TYPED_CONSTANT. */
+ struct debug_typed_constant *typed_constant;
+ } u;
+};
+
+/* During debug_write, a linked list of these structures is used to
+ keep track of ID numbers that have been assigned to classes. */
+
+struct debug_class_id
+{
+ /* Next ID number. */
+ struct debug_class_id *next;
+ /* The type with the ID. */
+ struct debug_type *type;
+ /* The tag; NULL if no tag. */
+ const char *tag;
+};
+
+/* During debug_type_samep, a linked list of these structures is kept
+ on the stack to avoid infinite recursion. */
+
+struct debug_type_compare_list
+{
+ /* Next type on list. */
+ struct debug_type_compare_list *next;
+ /* The types we are comparing. */
+ struct debug_type *t1;
+ struct debug_type *t2;
+};
+
+/* Local functions. */
+
+static void debug_error PARAMS ((const char *));
+static struct debug_name *debug_add_to_namespace
+ PARAMS ((struct debug_handle *, struct debug_namespace **, const char *,
+ enum debug_object_kind, enum debug_object_linkage));
+static struct debug_name *debug_add_to_current_namespace
+ PARAMS ((struct debug_handle *, const char *, enum debug_object_kind,
+ enum debug_object_linkage));
+static struct debug_type *debug_make_type
+ PARAMS ((struct debug_handle *, enum debug_type_kind, unsigned int));
+static struct debug_type *debug_get_real_type PARAMS ((PTR, debug_type));
+static boolean debug_write_name
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ struct debug_name *));
+static boolean debug_write_type
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ struct debug_type *, struct debug_name *));
+static boolean debug_write_class_type
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ struct debug_type *, const char *));
+static boolean debug_write_function
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ const char *, enum debug_object_linkage, struct debug_function *));
+static boolean debug_write_block
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ struct debug_block *));
+static boolean debug_write_linenos
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ bfd_vma));
+static boolean debug_set_class_id
+ PARAMS ((struct debug_handle *, const char *, struct debug_type *));
+static boolean debug_type_samep
+ PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *));
+static boolean debug_class_type_samep
+ PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *));
+
+/* Issue an error message. */
+
+static void
+debug_error (message)
+ const char *message;
+{
+ fprintf (stderr, "%s\n", message);
+}
+
+/* Add an object to a namespace. */
+
+static struct debug_name *
+debug_add_to_namespace (info, nsp, name, kind, linkage)
+ struct debug_handle *info;
+ struct debug_namespace **nsp;
+ const char *name;
+ enum debug_object_kind kind;
+ enum debug_object_linkage linkage;
+{
+ struct debug_name *n;
+ struct debug_namespace *ns;
+
+ n = (struct debug_name *) xmalloc (sizeof *n);
+ memset (n, 0, sizeof *n);
+
+ n->name = name;
+ n->kind = kind;
+ n->linkage = linkage;
+
+ ns = *nsp;
+ if (ns == NULL)
+ {
+ ns = (struct debug_namespace *) xmalloc (sizeof *ns);
+ memset (ns, 0, sizeof *ns);
+
+ ns->tail = &ns->list;
+
+ *nsp = ns;
+ }
+
+ *ns->tail = n;
+ ns->tail = &n->next;
+
+ return n;
+}
+
+/* Add an object to the current namespace. */
+
+static struct debug_name *
+debug_add_to_current_namespace (info, name, kind, linkage)
+ struct debug_handle *info;
+ const char *name;
+ enum debug_object_kind kind;
+ enum debug_object_linkage linkage;
+{
+ struct debug_namespace **nsp;
+
+ if (info->current_unit == NULL
+ || info->current_file == NULL)
+ {
+ debug_error ("debug_add_to_current_namespace: no current file");
+ return NULL;
+ }
+
+ if (info->current_block != NULL)
+ nsp = &info->current_block->locals;
+ else
+ nsp = &info->current_file->globals;
+
+ return debug_add_to_namespace (info, nsp, name, kind, linkage);
+}
+
+/* Return a handle for debugging information. */
+
+PTR
+debug_init ()
+{
+ struct debug_handle *ret;
+
+ ret = (struct debug_handle *) xmalloc (sizeof *ret);
+ memset (ret, 0, sizeof *ret);
+ return (PTR) ret;
+}
+
+/* Set the source filename. This implicitly starts a new compilation
+ unit. */
+
+boolean
+debug_set_filename (handle, name)
+ PTR handle;
+ const char *name;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_file *nfile;
+ struct debug_unit *nunit;
+
+ if (name == NULL)
+ name = "";
+
+ nfile = (struct debug_file *) xmalloc (sizeof *nfile);
+ memset (nfile, 0, sizeof *nfile);
+
+ nfile->filename = name;
+
+ nunit = (struct debug_unit *) xmalloc (sizeof *nunit);
+ memset (nunit, 0, sizeof *nunit);
+
+ nunit->files = nfile;
+ info->current_file = nfile;
+
+ if (info->current_unit != NULL)
+ info->current_unit->next = nunit;
+ else
+ {
+ assert (info->units == NULL);
+ info->units = nunit;
+ }
+
+ info->current_unit = nunit;
+
+ info->current_function = NULL;
+ info->current_block = NULL;
+ info->current_lineno = NULL;
+
+ return true;
+}
+
+/* Change source files to the given file name. This is used for
+ include files in a single compilation unit. */
+
+boolean
+debug_start_source (handle, name)
+ PTR handle;
+ const char *name;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_file *f, **pf;
+
+ if (name == NULL)
+ name = "";
+
+ if (info->current_unit == NULL)
+ {
+ debug_error ("debug_start_source: no debug_set_filename call");
+ return false;
+ }
+
+ for (f = info->current_unit->files; f != NULL; f = f->next)
+ {
+ if (f->filename[0] == name[0]
+ && f->filename[1] == name[1]
+ && strcmp (f->filename, name) == 0)
+ {
+ info->current_file = f;
+ return true;
+ }
+ }
+
+ f = (struct debug_file *) xmalloc (sizeof *f);
+ memset (f, 0, sizeof *f);
+
+ f->filename = name;
+
+ for (pf = &info->current_file->next;
+ *pf != NULL;
+ pf = &(*pf)->next)
+ ;
+ *pf = f;
+
+ info->current_file = f;
+
+ return true;
+}
+
+/* Record a function definition. This implicitly starts a function
+ block. The debug_type argument is the type of the return value.
+ The boolean indicates whether the function is globally visible.
+ The bfd_vma is the address of the start of the function. Currently
+ the parameter types are specified by calls to
+ debug_record_parameter. FIXME: There is no way to specify nested
+ functions. */
+
+boolean
+debug_record_function (handle, name, return_type, global, addr)
+ PTR handle;
+ const char *name;
+ debug_type return_type;
+ boolean global;
+ bfd_vma addr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_function *f;
+ struct debug_block *b;
+ struct debug_name *n;
+
+ if (name == NULL)
+ name = "";
+ if (return_type == NULL)
+ return false;
+
+ if (info->current_unit == NULL)
+ {
+ debug_error ("debug_record_function: no debug_set_filename call");
+ return false;
+ }
+
+ f = (struct debug_function *) xmalloc (sizeof *f);
+ memset (f, 0, sizeof *f);
+
+ f->return_type = return_type;
+
+ b = (struct debug_block *) xmalloc (sizeof *b);
+ memset (b, 0, sizeof *b);
+
+ b->start = addr;
+ b->end = (bfd_vma) -1;
+
+ f->blocks = b;
+
+ info->current_function = f;
+ info->current_block = b;
+
+ /* FIXME: If we could handle nested functions, this would be the
+ place: we would want to use a different namespace. */
+ n = debug_add_to_namespace (info,
+ &info->current_file->globals,
+ name,
+ DEBUG_OBJECT_FUNCTION,
+ (global
+ ? DEBUG_LINKAGE_GLOBAL
+ : DEBUG_LINKAGE_STATIC));
+ if (n == NULL)
+ return false;
+
+ n->u.function = f;
+
+ return true;
+}
+
+/* Record a parameter for the current function. */
+
+boolean
+debug_record_parameter (handle, name, type, kind, val)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ enum debug_parm_kind kind;
+ bfd_vma val;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_parameter *p, **pp;
+
+ if (name == NULL || type == NULL)
+ return false;
+
+ if (info->current_unit == NULL
+ || info->current_function == NULL)
+ {
+ debug_error ("debug_record_parameter: no current function");
+ return false;
+ }
+
+ p = (struct debug_parameter *) xmalloc (sizeof *p);
+ memset (p, 0, sizeof *p);
+
+ p->name = name;
+ p->type = type;
+ p->kind = kind;
+ p->val = val;
+
+ for (pp = &info->current_function->parameters;
+ *pp != NULL;
+ pp = &(*pp)->next)
+ ;
+ *pp = p;
+
+ return true;
+}
+
+/* End a function. FIXME: This should handle function nesting. */
+
+boolean
+debug_end_function (handle, addr)
+ PTR handle;
+ bfd_vma addr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+
+ if (info->current_unit == NULL
+ || info->current_block == NULL
+ || info->current_function == NULL)
+ {
+ debug_error ("debug_end_function: no current function");
+ return false;
+ }
+
+ if (info->current_block->parent != NULL)
+ {
+ debug_error ("debug_end_function: some blocks were not closed");
+ return false;
+ }
+
+ info->current_block->end = addr;
+
+ info->current_function = NULL;
+ info->current_block = NULL;
+
+ return true;
+}
+
+/* Start a block in a function. All local information will be
+ recorded in this block, until the matching call to debug_end_block.
+ debug_start_block and debug_end_block may be nested. The bfd_vma
+ argument is the address at which this block starts. */
+
+boolean
+debug_start_block (handle, addr)
+ PTR handle;
+ bfd_vma addr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_block *b, **pb;
+
+ /* We must always have a current block: debug_record_function sets
+ one up. */
+ if (info->current_unit == NULL
+ || info->current_block == NULL)
+ {
+ debug_error ("debug_start_block: no current block");
+ return false;
+ }
+
+ b = (struct debug_block *) xmalloc (sizeof *b);
+ memset (b, 0, sizeof *b);
+
+ b->parent = info->current_block;
+ b->start = addr;
+ b->end = (bfd_vma) -1;
+
+ /* This new block is a child of the current block. */
+ for (pb = &info->current_block->children;
+ *pb != NULL;
+ pb = &(*pb)->next)
+ ;
+ *pb = b;
+
+ info->current_block = b;
+
+ return true;
+}
+
+/* Finish a block in a function. This matches the call to
+ debug_start_block. The argument is the address at which this block
+ ends. */
+
+boolean
+debug_end_block (handle, addr)
+ PTR handle;
+ bfd_vma addr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_block *parent;
+
+ if (info->current_unit == NULL
+ || info->current_block == NULL)
+ {
+ debug_error ("debug_end_block: no current block");
+ return false;
+ }
+
+ parent = info->current_block->parent;
+ if (parent == NULL)
+ {
+ debug_error ("debug_end_block: attempt to close top level block");
+ return false;
+ }
+
+ info->current_block->end = addr;
+
+ info->current_block = parent;
+
+ return true;
+}
+
+/* Associate a line number in the current source file and function
+ with a given address. */
+
+boolean
+debug_record_line (handle, lineno, addr)
+ PTR handle;
+ unsigned long lineno;
+ bfd_vma addr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_lineno *l;
+ unsigned int i;
+
+ if (info->current_unit == NULL)
+ {
+ debug_error ("debug_record_line: no current unit");
+ return false;
+ }
+
+ l = info->current_lineno;
+ if (l != NULL && l->file == info->current_file)
+ {
+ for (i = 0; i < DEBUG_LINENO_COUNT; i++)
+ {
+ if (l->linenos[i] == (unsigned long) -1)
+ {
+ l->linenos[i] = lineno;
+ l->addrs[i] = addr;
+ return true;
+ }
+ }
+ }
+
+ /* If we get here, then either 1) there is no current_lineno
+ structure, which means this is the first line number in this
+ compilation unit, 2) the current_lineno structure is for a
+ different file, or 3) the current_lineno structure is full.
+ Regardless, we want to allocate a new debug_lineno structure, put
+ it in the right place, and make it the new current_lineno
+ structure. */
+
+ l = (struct debug_lineno *) xmalloc (sizeof *l);
+ memset (l, 0, sizeof *l);
+
+ l->file = info->current_file;
+ l->linenos[0] = lineno;
+ l->addrs[0] = addr;
+ for (i = 1; i < DEBUG_LINENO_COUNT; i++)
+ l->linenos[i] = (unsigned long) -1;
+
+ if (info->current_lineno != NULL)
+ info->current_lineno->next = l;
+ else
+ info->current_unit->linenos = l;
+
+ info->current_lineno = l;
+
+ return true;
+}
+
+/* Start a named common block. This is a block of variables that may
+ move in memory. */
+
+boolean
+debug_start_common_block (handle, name)
+ PTR handle;
+ const char *name;
+{
+ /* FIXME */
+ debug_error ("debug_start_common_block: not implemented");
+ return false;
+}
+
+/* End a named common block. */
+
+boolean
+debug_end_common_block (handle, name)
+ PTR handle;
+ const char *name;
+{
+ /* FIXME */
+ debug_error ("debug_end_common_block: not implemented");
+ return false;
+}
+
+/* Record a named integer constant. */
+
+boolean
+debug_record_int_const (handle, name, val)
+ PTR handle;
+ const char *name;
+ bfd_vma val;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_name *n;
+
+ if (name == NULL)
+ return false;
+
+ n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_INT_CONSTANT,
+ DEBUG_LINKAGE_NONE);
+ if (n == NULL)
+ return false;
+
+ n->u.int_constant = val;
+
+ return true;
+}
+
+/* Record a named floating point constant. */
+
+boolean
+debug_record_float_const (handle, name, val)
+ PTR handle;
+ const char *name;
+ double val;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_name *n;
+
+ if (name == NULL)
+ return false;
+
+ n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_FLOAT_CONSTANT,
+ DEBUG_LINKAGE_NONE);
+ if (n == NULL)
+ return false;
+
+ n->u.float_constant = val;
+
+ return true;
+}
+
+/* Record a typed constant with an integral value. */
+
+boolean
+debug_record_typed_const (handle, name, type, val)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ bfd_vma val;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_name *n;
+ struct debug_typed_constant *tc;
+
+ if (name == NULL || type == NULL)
+ return false;
+
+ n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_TYPED_CONSTANT,
+ DEBUG_LINKAGE_NONE);
+ if (n == NULL)
+ return false;
+
+ tc = (struct debug_typed_constant *) xmalloc (sizeof *tc);
+ memset (tc, 0, sizeof *tc);
+
+ tc->type = type;
+ tc->val = val;
+
+ n->u.typed_constant = tc;
+
+ return true;
+}
+
+/* Record a label. */
+
+boolean
+debug_record_label (handle, name, type, addr)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ bfd_vma addr;
+{
+ /* FIXME. */
+ debug_error ("debug_record_label not implemented");
+ return false;
+}
+
+/* Record a variable. */
+
+boolean
+debug_record_variable (handle, name, type, kind, val)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ enum debug_var_kind kind;
+ bfd_vma val;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_namespace **nsp;
+ enum debug_object_linkage linkage;
+ struct debug_name *n;
+ struct debug_variable *v;
+
+ if (name == NULL || type == NULL)
+ return false;
+
+ if (info->current_unit == NULL
+ || info->current_file == NULL)
+ {
+ debug_error ("debug_record_variable: no current file");
+ return false;
+ }
+
+ if (kind == DEBUG_GLOBAL || kind == DEBUG_STATIC)
+ {
+ nsp = &info->current_file->globals;
+ if (kind == DEBUG_GLOBAL)
+ linkage = DEBUG_LINKAGE_GLOBAL;
+ else
+ linkage = DEBUG_LINKAGE_STATIC;
+ }
+ else
+ {
+ if (info->current_block == NULL)
+ {
+ debug_error ("debug_record_variable: no current block");
+ return false;
+ }
+ nsp = &info->current_block->locals;
+ linkage = DEBUG_LINKAGE_AUTOMATIC;
+ }
+
+ n = debug_add_to_namespace (info, nsp, name, DEBUG_OBJECT_VARIABLE, linkage);
+ if (n == NULL)
+ return false;
+
+ v = (struct debug_variable *) xmalloc (sizeof *v);
+ memset (v, 0, sizeof *v);
+
+ v->kind = kind;
+ v->type = type;
+ v->val = val;
+
+ n->u.variable = v;
+
+ return true;
+}
+
+/* Make a type with a given kind and size. */
+
+/*ARGSUSED*/
+static struct debug_type *
+debug_make_type (info, kind, size)
+ struct debug_handle *info;
+ enum debug_type_kind kind;
+ unsigned int size;
+{
+ struct debug_type *t;
+
+ t = (struct debug_type *) xmalloc (sizeof *t);
+ memset (t, 0, sizeof *t);
+
+ t->kind = kind;
+ t->size = size;
+
+ return t;
+}
+
+/* Make an indirect type which may be used as a placeholder for a type
+ which is referenced before it is defined. */
+
+debug_type
+debug_make_indirect_type (handle, slot, tag)
+ PTR handle;
+ debug_type *slot;
+ const char *tag;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_indirect_type *i;
+
+ t = debug_make_type (info, DEBUG_KIND_INDIRECT, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ i = (struct debug_indirect_type *) xmalloc (sizeof *i);
+ memset (i, 0, sizeof *i);
+
+ i->slot = slot;
+ i->tag = tag;
+
+ t->u.kindirect = i;
+
+ return t;
+}
+
+/* Make a void type. There is only one of these. */
+
+debug_type
+debug_make_void_type (handle)
+ PTR handle;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+
+ return debug_make_type (info, DEBUG_KIND_VOID, 0);
+}
+
+/* Make an integer type of a given size. The boolean argument is true
+ if the integer is unsigned. */
+
+debug_type
+debug_make_int_type (handle, size, unsignedp)
+ PTR handle;
+ unsigned int size;
+ boolean unsignedp;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ t = debug_make_type (info, DEBUG_KIND_INT, size);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t->u.kint = unsignedp;
+
+ return t;
+}
+
+/* Make a floating point type of a given size. FIXME: On some
+ platforms, like an Alpha, you probably need to be able to specify
+ the format. */
+
+debug_type
+debug_make_float_type (handle, size)
+ PTR handle;
+ unsigned int size;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+
+ return debug_make_type (info, DEBUG_KIND_FLOAT, size);
+}
+
+/* Make a boolean type of a given size. */
+
+debug_type
+debug_make_bool_type (handle, size)
+ PTR handle;
+ unsigned int size;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+
+ return debug_make_type (info, DEBUG_KIND_BOOL, size);
+}
+
+/* Make a complex type of a given size. */
+
+debug_type
+debug_make_complex_type (handle, size)
+ PTR handle;
+ unsigned int size;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+
+ return debug_make_type (info, DEBUG_KIND_COMPLEX, size);
+}
+
+/* Make a structure type. The second argument is true for a struct,
+ false for a union. The third argument is the size of the struct.
+ The fourth argument is a NULL terminated array of fields. */
+
+debug_type
+debug_make_struct_type (handle, structp, size, fields)
+ PTR handle;
+ boolean structp;
+ bfd_vma size;
+ debug_field *fields;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_class_type *c;
+
+ t = debug_make_type (info,
+ structp ? DEBUG_KIND_STRUCT : DEBUG_KIND_UNION,
+ size);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ c = (struct debug_class_type *) xmalloc (sizeof *c);
+ memset (c, 0, sizeof *c);
+
+ c->fields = fields;
+
+ t->u.kclass = c;
+
+ return t;
+}
+
+/* Make an object type. The first three arguments after the handle
+ are the same as for debug_make_struct_type. The next arguments are
+ a NULL terminated array of base classes, a NULL terminated array of
+ methods, the type of the object holding the virtual function table
+ if it is not this object, and a boolean which is true if this
+ object has its own virtual function table. */
+
+debug_type
+debug_make_object_type (handle, structp, size, fields, baseclasses,
+ methods, vptrbase, ownvptr)
+ PTR handle;
+ boolean structp;
+ bfd_vma size;
+ debug_field *fields;
+ debug_baseclass *baseclasses;
+ debug_method *methods;
+ debug_type vptrbase;
+ boolean ownvptr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_class_type *c;
+
+ t = debug_make_type (info,
+ structp ? DEBUG_KIND_CLASS : DEBUG_KIND_UNION_CLASS,
+ size);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ c = (struct debug_class_type *) xmalloc (sizeof *c);
+ memset (c, 0, sizeof *c);
+
+ c->fields = fields;
+ c->baseclasses = baseclasses;
+ c->methods = methods;
+ if (ownvptr)
+ c->vptrbase = t;
+ else
+ c->vptrbase = vptrbase;
+
+ t->u.kclass = c;
+
+ return t;
+}
+
+/* Make an enumeration type. The arguments are a null terminated
+ array of strings, and an array of corresponding values. */
+
+debug_type
+debug_make_enum_type (handle, names, values)
+ PTR handle;
+ const char **names;
+ bfd_signed_vma *values;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_enum_type *e;
+
+ t = debug_make_type (info, DEBUG_KIND_ENUM, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ e = (struct debug_enum_type *) xmalloc (sizeof *e);
+ memset (e, 0, sizeof *e);
+
+ e->names = names;
+ e->values = values;
+
+ t->u.kenum = e;
+
+ return t;
+}
+
+/* Make a pointer to a given type. */
+
+debug_type
+debug_make_pointer_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (type->pointer != DEBUG_TYPE_NULL)
+ return type->pointer;
+
+ t = debug_make_type (info, DEBUG_KIND_POINTER, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t->u.kpointer = type;
+
+ type->pointer = t;
+
+ return t;
+}
+
+/* Make a function returning a given type. FIXME: We should be able
+ to record the parameter types. */
+
+debug_type
+debug_make_function_type (handle, type, arg_types, varargs)
+ PTR handle;
+ debug_type type;
+ debug_type *arg_types;
+ boolean varargs;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_function_type *f;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_FUNCTION, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ f = (struct debug_function_type *) xmalloc (sizeof *f);
+ memset (f, 0, sizeof *f);
+
+ f->return_type = type;
+ f->arg_types = arg_types;
+ f->varargs = varargs;
+
+ t->u.kfunction = f;
+
+ return t;
+}
+
+/* Make a reference to a given type. */
+
+debug_type
+debug_make_reference_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_REFERENCE, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t->u.kreference = type;
+
+ return t;
+}
+
+/* Make a range of a given type from a lower to an upper bound. */
+
+debug_type
+debug_make_range_type (handle, type, lower, upper)
+ PTR handle;
+ debug_type type;
+ bfd_signed_vma lower;
+ bfd_signed_vma upper;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_range_type *r;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_RANGE, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ r = (struct debug_range_type *) xmalloc (sizeof *r);
+ memset (r, 0, sizeof *r);
+
+ r->type = type;
+ r->lower = lower;
+ r->upper = upper;
+
+ t->u.krange = r;
+
+ return t;
+}
+
+/* Make an array type. The second argument is the type of an element
+ of the array. The third argument is the type of a range of the
+ array. The fourth and fifth argument are the lower and upper
+ bounds, respectively. The sixth argument is true if this array is
+ actually a string, as in C. */
+
+debug_type
+debug_make_array_type (handle, element_type, range_type, lower, upper,
+ stringp)
+ PTR handle;
+ debug_type element_type;
+ debug_type range_type;
+ bfd_signed_vma lower;
+ bfd_signed_vma upper;
+ boolean stringp;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_array_type *a;
+
+ if (element_type == NULL || range_type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_ARRAY, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ a = (struct debug_array_type *) xmalloc (sizeof *a);
+ memset (a, 0, sizeof *a);
+
+ a->element_type = element_type;
+ a->range_type = range_type;
+ a->lower = lower;
+ a->upper = upper;
+ a->stringp = stringp;
+
+ t->u.karray = a;
+
+ return t;
+}
+
+/* Make a set of a given type. For example, a Pascal set type. The
+ boolean argument is true if this set is actually a bitstring, as in
+ CHILL. */
+
+debug_type
+debug_make_set_type (handle, type, bitstringp)
+ PTR handle;
+ debug_type type;
+ boolean bitstringp;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_set_type *s;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_SET, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ s = (struct debug_set_type *) xmalloc (sizeof *s);
+ memset (s, 0, sizeof *s);
+
+ s->type = type;
+ s->bitstringp = bitstringp;
+
+ t->u.kset = s;
+
+ return t;
+}
+
+/* Make a type for a pointer which is relative to an object. The
+ second argument is the type of the object to which the pointer is
+ relative. The third argument is the type that the pointer points
+ to. */
+
+debug_type
+debug_make_offset_type (handle, base_type, target_type)
+ PTR handle;
+ debug_type base_type;
+ debug_type target_type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_offset_type *o;
+
+ if (base_type == NULL || target_type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_OFFSET, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ o = (struct debug_offset_type *) xmalloc (sizeof *o);
+ memset (o, 0, sizeof *o);
+
+ o->base_type = base_type;
+ o->target_type = target_type;
+
+ t->u.koffset = o;
+
+ return t;
+}
+
+/* Make a type for a method function. The second argument is the
+ return type, the third argument is the domain, and the fourth
+ argument is a NULL terminated array of argument types. */
+
+debug_type
+debug_make_method_type (handle, return_type, domain_type, arg_types, varargs)
+ PTR handle;
+ debug_type return_type;
+ debug_type domain_type;
+ debug_type *arg_types;
+ boolean varargs;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_method_type *m;
+
+ if (return_type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_METHOD, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ m = (struct debug_method_type *) xmalloc (sizeof *m);
+ memset (m, 0, sizeof *m);
+
+ m->return_type = return_type;
+ m->domain_type = domain_type;
+ m->arg_types = arg_types;
+ m->varargs = varargs;
+
+ t->u.kmethod = m;
+
+ return t;
+}
+
+/* Make a const qualified version of a given type. */
+
+debug_type
+debug_make_const_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_CONST, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t->u.kconst = type;
+
+ return t;
+}
+
+/* Make a volatile qualified version of a given type. */
+
+debug_type
+debug_make_volatile_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_VOLATILE, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t->u.kvolatile = type;
+
+ return t;
+}
+
+/* Make an undefined tagged type. For example, a struct which has
+ been mentioned, but not defined. */
+
+debug_type
+debug_make_undefined_tagged_type (handle, name, kind)
+ PTR handle;
+ const char *name;
+ enum debug_type_kind kind;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ if (name == NULL)
+ return DEBUG_TYPE_NULL;
+
+ switch (kind)
+ {
+ case DEBUG_KIND_STRUCT:
+ case DEBUG_KIND_UNION:
+ case DEBUG_KIND_CLASS:
+ case DEBUG_KIND_UNION_CLASS:
+ case DEBUG_KIND_ENUM:
+ break;
+
+ default:
+ debug_error ("debug_make_undefined_type: unsupported kind");
+ return DEBUG_TYPE_NULL;
+ }
+
+ t = debug_make_type (info, kind, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ return debug_tag_type (handle, name, t);
+}
+
+/* Make a base class for an object. The second argument is the base
+ class type. The third argument is the bit position of this base
+ class in the object (always 0 unless doing multiple inheritance).
+ The fourth argument is whether this is a virtual class. The fifth
+ argument is the visibility of the base class. */
+
+/*ARGSUSED*/
+debug_baseclass
+debug_make_baseclass (handle, type, bitpos, virtual, visibility)
+ PTR handle;
+ debug_type type;
+ bfd_vma bitpos;
+ boolean virtual;
+ enum debug_visibility visibility;
+{
+ struct debug_baseclass *b;
+
+ b = (struct debug_baseclass *) xmalloc (sizeof *b);
+ memset (b, 0, sizeof *b);
+
+ b->type = type;
+ b->bitpos = bitpos;
+ b->virtual = virtual;
+ b->visibility = visibility;
+
+ return b;
+}
+
+/* Make a field for a struct. The second argument is the name. The
+ third argument is the type of the field. The fourth argument is
+ the bit position of the field. The fifth argument is the size of
+ the field (it may be zero). The sixth argument is the visibility
+ of the field. */
+
+/*ARGSUSED*/
+debug_field
+debug_make_field (handle, name, type, bitpos, bitsize, visibility)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ bfd_vma bitpos;
+ bfd_vma bitsize;
+ enum debug_visibility visibility;
+{
+ struct debug_field *f;
+
+ f = (struct debug_field *) xmalloc (sizeof *f);
+ memset (f, 0, sizeof *f);
+
+ f->name = name;
+ f->type = type;
+ f->static_member = false;
+ f->u.f.bitpos = bitpos;
+ f->u.f.bitsize = bitsize;
+ f->visibility = visibility;
+
+ return f;
+}
+
+/* Make a static member of an object. The second argument is the
+ name. The third argument is the type of the member. The fourth
+ argument is the physical name of the member (i.e., the name as a
+ global variable). The fifth argument is the visibility of the
+ member. */
+
+/*ARGSUSED*/
+debug_field
+debug_make_static_member (handle, name, type, physname, visibility)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ const char *physname;
+ enum debug_visibility visibility;
+{
+ struct debug_field *f;
+
+ f = (struct debug_field *) xmalloc (sizeof *f);
+ memset (f, 0, sizeof *f);
+
+ f->name = name;
+ f->type = type;
+ f->static_member = true;
+ f->u.s.physname = physname;
+ f->visibility = visibility;
+
+ return f;
+}
+
+/* Make a method. The second argument is the name, and the third
+ argument is a NULL terminated array of method variants. */
+
+/*ARGSUSED*/
+debug_method
+debug_make_method (handle, name, variants)
+ PTR handle;
+ const char *name;
+ debug_method_variant *variants;
+{
+ struct debug_method *m;
+
+ m = (struct debug_method *) xmalloc (sizeof *m);
+ memset (m, 0, sizeof *m);
+
+ m->name = name;
+ m->variants = variants;
+
+ return m;
+}
+
+/* Make a method argument. The second argument is the real name of
+ the function. The third argument is the type of the function. The
+ fourth argument is the visibility. The fifth argument is whether
+ this is a const function. The sixth argument is whether this is a
+ volatile function. The seventh argument is the offset in the
+ virtual function table, if any. The eighth argument is the virtual
+ function context. FIXME: Are the const and volatile arguments
+ necessary? Could we just use debug_make_const_type? */
+
+/*ARGSUSED*/
+debug_method_variant
+debug_make_method_variant (handle, physname, type, visibility, constp,
+ volatilep, voffset, context)
+ PTR handle;
+ const char *physname;
+ debug_type type;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ debug_type context;
+{
+ struct debug_method_variant *m;
+
+ m = (struct debug_method_variant *) xmalloc (sizeof *m);
+ memset (m, 0, sizeof *m);
+
+ m->physname = physname;
+ m->type = type;
+ m->visibility = visibility;
+ m->constp = constp;
+ m->volatilep = volatilep;
+ m->voffset = voffset;
+ m->context = context;
+
+ return m;
+}
+
+/* Make a static method argument. The arguments are the same as for
+ debug_make_method_variant, except that the last two are omitted
+ since a static method can not also be virtual. */
+
+debug_method_variant
+debug_make_static_method_variant (handle, physname, type, visibility,
+ constp, volatilep)
+ PTR handle;
+ const char *physname;
+ debug_type type;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+{
+ struct debug_method_variant *m;
+
+ m = (struct debug_method_variant *) xmalloc (sizeof *m);
+ memset (m, 0, sizeof *m);
+
+ m->physname = physname;
+ m->type = type;
+ m->visibility = visibility;
+ m->constp = constp;
+ m->volatilep = volatilep;
+ m->voffset = VOFFSET_STATIC_METHOD;
+
+ return m;
+}
+
+/* Name a type. */
+
+debug_type
+debug_name_type (handle, name, type)
+ PTR handle;
+ const char *name;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_named_type *n;
+ struct debug_name *nm;
+
+ if (name == NULL || type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (info->current_unit == NULL
+ || info->current_file == NULL)
+ {
+ debug_error ("debug_record_variable: no current file");
+ return false;
+ }
+
+ t = debug_make_type (info, DEBUG_KIND_NAMED, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ n = (struct debug_named_type *) xmalloc (sizeof *n);
+ memset (n, 0, sizeof *n);
+
+ n->type = type;
+
+ t->u.knamed = n;
+
+ /* We always add the name to the global namespace. This is probably
+ wrong in some cases, but it seems to be right for stabs. FIXME. */
+
+ nm = debug_add_to_namespace (info, &info->current_file->globals, name,
+ DEBUG_OBJECT_TYPE, DEBUG_LINKAGE_NONE);
+ if (nm == NULL)
+ return false;
+
+ nm->u.type = t;
+
+ n->name = nm;
+
+ return t;
+}
+
+/* Tag a type. */
+
+debug_type
+debug_tag_type (handle, name, type)
+ PTR handle;
+ const char *name;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_named_type *n;
+ struct debug_name *nm;
+
+ if (name == NULL || type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (info->current_file == NULL)
+ {
+ debug_error ("debug_tag_type: no current file");
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (type->kind == DEBUG_KIND_TAGGED)
+ {
+ if (strcmp (type->u.knamed->name->name, name) == 0)
+ return type;
+ debug_error ("debug_tag_type: extra tag attempted");
+ return DEBUG_TYPE_NULL;
+ }
+
+ t = debug_make_type (info, DEBUG_KIND_TAGGED, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ n = (struct debug_named_type *) xmalloc (sizeof *n);
+ memset (n, 0, sizeof *n);
+
+ n->type = type;
+
+ t->u.knamed = n;
+
+ /* We keep a global namespace of tags for each compilation unit. I
+ don't know if that is the right thing to do. */
+
+ nm = debug_add_to_namespace (info, &info->current_file->globals, name,
+ DEBUG_OBJECT_TAG, DEBUG_LINKAGE_NONE);
+ if (nm == NULL)
+ return false;
+
+ nm->u.tag = t;
+
+ n->name = nm;
+
+ return t;
+}
+
+/* Record the size of a given type. */
+
+/*ARGSUSED*/
+boolean
+debug_record_type_size (handle, type, size)
+ PTR handle;
+ debug_type type;
+ unsigned int size;
+{
+ if (type->size != 0 && type->size != size)
+ fprintf (stderr, "Warning: changing type size from %d to %d\n",
+ type->size, size);
+
+ type->size = size;
+
+ return true;
+}
+
+/* Find a named type. */
+
+debug_type
+debug_find_named_type (handle, name)
+ PTR handle;
+ const char *name;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_block *b;
+ struct debug_file *f;
+
+ /* We only search the current compilation unit. I don't know if
+ this is right or not. */
+
+ if (info->current_unit == NULL)
+ {
+ debug_error ("debug_find_named_type: no current compilation unit");
+ return DEBUG_TYPE_NULL;
+ }
+
+ for (b = info->current_block; b != NULL; b = b->parent)
+ {
+ if (b->locals != NULL)
+ {
+ struct debug_name *n;
+
+ for (n = b->locals->list; n != NULL; n = n->next)
+ {
+ if (n->kind == DEBUG_OBJECT_TYPE
+ && n->name[0] == name[0]
+ && strcmp (n->name, name) == 0)
+ return n->u.type;
+ }
+ }
+ }
+
+ for (f = info->current_unit->files; f != NULL; f = f->next)
+ {
+ if (f->globals != NULL)
+ {
+ struct debug_name *n;
+
+ for (n = f->globals->list; n != NULL; n = n->next)
+ {
+ if (n->kind == DEBUG_OBJECT_TYPE
+ && n->name[0] == name[0]
+ && strcmp (n->name, name) == 0)
+ return n->u.type;
+ }
+ }
+ }
+
+ return DEBUG_TYPE_NULL;
+}
+
+/* Find a tagged type. */
+
+debug_type
+debug_find_tagged_type (handle, name, kind)
+ PTR handle;
+ const char *name;
+ enum debug_type_kind kind;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_unit *u;
+
+ /* We search the globals of all the compilation units. I don't know
+ if this is correct or not. It would be easy to change. */
+
+ for (u = info->units; u != NULL; u = u->next)
+ {
+ struct debug_file *f;
+
+ for (f = u->files; f != NULL; f = f->next)
+ {
+ struct debug_name *n;
+
+ if (f->globals != NULL)
+ {
+ for (n = f->globals->list; n != NULL; n = n->next)
+ {
+ if (n->kind == DEBUG_OBJECT_TAG
+ && (kind == DEBUG_KIND_ILLEGAL
+ || n->u.tag->kind == kind)
+ && n->name[0] == name[0]
+ && strcmp (n->name, name) == 0)
+ return n->u.tag;
+ }
+ }
+ }
+ }
+
+ return DEBUG_TYPE_NULL;
+}
+
+/* Get a base type. */
+
+static struct debug_type *
+debug_get_real_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ switch (type->kind)
+ {
+ default:
+ return type;
+ case DEBUG_KIND_INDIRECT:
+ if (*type->u.kindirect->slot != NULL)
+ return debug_get_real_type (handle, *type->u.kindirect->slot);
+ return type;
+ case DEBUG_KIND_NAMED:
+ case DEBUG_KIND_TAGGED:
+ return debug_get_real_type (handle, type->u.knamed->type);
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the kind of a type. */
+
+enum debug_type_kind
+debug_get_type_kind (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type == NULL)
+ return DEBUG_KIND_ILLEGAL;
+ type = debug_get_real_type (handle, type);
+ return type->kind;
+}
+
+/* Get the name of a type. */
+
+const char *
+debug_get_type_name (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type->kind == DEBUG_KIND_INDIRECT)
+ {
+ if (*type->u.kindirect->slot != NULL)
+ return debug_get_type_name (handle, *type->u.kindirect->slot);
+ return type->u.kindirect->tag;
+ }
+ if (type->kind == DEBUG_KIND_NAMED
+ || type->kind == DEBUG_KIND_TAGGED)
+ return type->u.knamed->name->name;
+ return NULL;
+}
+
+/* Get the size of a type. */
+
+bfd_vma
+debug_get_type_size (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type == NULL)
+ return 0;
+
+ /* We don't call debug_get_real_type, because somebody might have
+ called debug_record_type_size on a named or indirect type. */
+
+ if (type->size != 0)
+ return type->size;
+
+ switch (type->kind)
+ {
+ default:
+ return 0;
+ case DEBUG_KIND_INDIRECT:
+ if (*type->u.kindirect->slot != NULL)
+ return debug_get_type_size (handle, *type->u.kindirect->slot);
+ return 0;
+ case DEBUG_KIND_NAMED:
+ case DEBUG_KIND_TAGGED:
+ return debug_get_type_size (handle, type->u.knamed->type);
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the return type of a function or method type. */
+
+debug_type
+debug_get_return_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+ type = debug_get_real_type (handle, type);
+ switch (type->kind)
+ {
+ default:
+ return DEBUG_TYPE_NULL;
+ case DEBUG_KIND_FUNCTION:
+ return type->u.kfunction->return_type;
+ case DEBUG_KIND_METHOD:
+ return type->u.kmethod->return_type;
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the parameter types of a function or method type (except that
+ we don't currently store the parameter types of a function). */
+
+const debug_type *
+debug_get_parameter_types (handle, type, pvarargs)
+ PTR handle;
+ debug_type type;
+ boolean *pvarargs;
+{
+ if (type == NULL)
+ return NULL;
+ type = debug_get_real_type (handle, type);
+ switch (type->kind)
+ {
+ default:
+ return NULL;
+ case DEBUG_KIND_FUNCTION:
+ *pvarargs = type->u.kfunction->varargs;
+ return type->u.kfunction->arg_types;
+ case DEBUG_KIND_METHOD:
+ *pvarargs = type->u.kmethod->varargs;
+ return type->u.kmethod->arg_types;
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the target type of a type. */
+
+debug_type
+debug_get_target_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type == NULL)
+ return NULL;
+ type = debug_get_real_type (handle, type);
+ switch (type->kind)
+ {
+ default:
+ return NULL;
+ case DEBUG_KIND_POINTER:
+ return type->u.kpointer;
+ case DEBUG_KIND_REFERENCE:
+ return type->u.kreference;
+ case DEBUG_KIND_CONST:
+ return type->u.kconst;
+ case DEBUG_KIND_VOLATILE:
+ return type->u.kvolatile;
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the NULL terminated array of fields for a struct, union, or
+ class. */
+
+const debug_field *
+debug_get_fields (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type == NULL)
+ return NULL;
+ type = debug_get_real_type (handle, type);
+ switch (type->kind)
+ {
+ default:
+ return NULL;
+ case DEBUG_KIND_STRUCT:
+ case DEBUG_KIND_UNION:
+ case DEBUG_KIND_CLASS:
+ case DEBUG_KIND_UNION_CLASS:
+ return type->u.kclass->fields;
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the type of a field. */
+
+/*ARGSUSED*/
+debug_type
+debug_get_field_type (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL)
+ return NULL;
+ return field->type;
+}
+
+/* Get the name of a field. */
+
+/*ARGSUSED*/
+const char *
+debug_get_field_name (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL)
+ return NULL;
+ return field->name;
+}
+
+/* Get the bit position of a field. */
+
+/*ARGSUSED*/
+bfd_vma
+debug_get_field_bitpos (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL || field->static_member)
+ return (bfd_vma) -1;
+ return field->u.f.bitpos;
+}
+
+/* Get the bit size of a field. */
+
+/*ARGSUSED*/
+bfd_vma
+debug_get_field_bitsize (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL || field->static_member)
+ return (bfd_vma) -1;
+ return field->u.f.bitsize;
+}
+
+/* Get the visibility of a field. */
+
+/*ARGSUSED*/
+enum debug_visibility
+debug_get_field_visibility (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL)
+ return DEBUG_VISIBILITY_IGNORE;
+ return field->visibility;
+}
+
+/* Get the physical name of a field. */
+
+const char *
+debug_get_field_physname (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL || ! field->static_member)
+ return NULL;
+ return field->u.s.physname;
+}
+
+/* Write out the debugging information. This is given a handle to
+ debugging information, and a set of function pointers to call. */
+
+boolean
+debug_write (handle, fns, fhandle)
+ PTR handle;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_unit *u;
+
+ /* We use a mark to tell whether we have already written out a
+ particular name. We use an integer, so that we don't have to
+ clear the mark fields if we happen to write out the same
+ information more than once. */
+ ++info->mark;
+
+ /* The base_id field holds an ID value which will never be used, so
+ that we can tell whether we have assigned an ID during this call
+ to debug_write. */
+ info->base_id = info->class_id;
+
+ /* We keep a linked list of classes for which was have assigned ID's
+ during this call to debug_write. */
+ info->id_list = NULL;
+
+ for (u = info->units; u != NULL; u = u->next)
+ {
+ struct debug_file *f;
+ boolean first_file;
+
+ info->current_write_lineno = u->linenos;
+ info->current_write_lineno_index = 0;
+
+ if (! (*fns->start_compilation_unit) (fhandle, u->files->filename))
+ return false;
+
+ first_file = true;
+ for (f = u->files; f != NULL; f = f->next)
+ {
+ struct debug_name *n;
+
+ if (first_file)
+ first_file = false;
+ else
+ {
+ if (! (*fns->start_source) (fhandle, f->filename))
+ return false;
+ }
+
+ if (f->globals != NULL)
+ {
+ for (n = f->globals->list; n != NULL; n = n->next)
+ {
+ if (! debug_write_name (info, fns, fhandle, n))
+ return false;
+ }
+ }
+ }
+
+ /* Output any line number information which hasn't already been
+ handled. */
+ if (! debug_write_linenos (info, fns, fhandle, (bfd_vma) -1))
+ return false;
+ }
+
+ return true;
+}
+
+/* Write out an element in a namespace. */
+
+static boolean
+debug_write_name (info, fns, fhandle, n)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ struct debug_name *n;
+{
+ switch (n->kind)
+ {
+ case DEBUG_OBJECT_TYPE:
+ if (! debug_write_type (info, fns, fhandle, n->u.type, n)
+ || ! (*fns->typdef) (fhandle, n->name))
+ return false;
+ return true;
+ case DEBUG_OBJECT_TAG:
+ if (! debug_write_type (info, fns, fhandle, n->u.tag, n))
+ return false;
+ return (*fns->tag) (fhandle, n->name);
+ case DEBUG_OBJECT_VARIABLE:
+ if (! debug_write_type (info, fns, fhandle, n->u.variable->type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->variable) (fhandle, n->name, n->u.variable->kind,
+ n->u.variable->val);
+ case DEBUG_OBJECT_FUNCTION:
+ return debug_write_function (info, fns, fhandle, n->name,
+ n->linkage, n->u.function);
+ case DEBUG_OBJECT_INT_CONSTANT:
+ return (*fns->int_constant) (fhandle, n->name, n->u.int_constant);
+ case DEBUG_OBJECT_FLOAT_CONSTANT:
+ return (*fns->float_constant) (fhandle, n->name, n->u.float_constant);
+ case DEBUG_OBJECT_TYPED_CONSTANT:
+ if (! debug_write_type (info, fns, fhandle, n->u.typed_constant->type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->typed_constant) (fhandle, n->name,
+ n->u.typed_constant->val);
+ default:
+ abort ();
+ return false;
+ }
+ /*NOTREACHED*/
+}
+
+/* Write out a type. If the type is DEBUG_KIND_NAMED or
+ DEBUG_KIND_TAGGED, then the name argument is the name for which we
+ are about to call typedef or tag. If the type is anything else,
+ then the name argument is a tag from a DEBUG_KIND_TAGGED type which
+ points to this one. */
+
+static boolean
+debug_write_type (info, fns, fhandle, type, name)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ struct debug_type *type;
+ struct debug_name *name;
+{
+ unsigned int i;
+ int is;
+ const char *tag;
+
+ /* If we have a name for this type, just output it. We only output
+ typedef names after they have been defined. We output type tags
+ whenever we are not actually defining them. */
+ if ((type->kind == DEBUG_KIND_NAMED
+ || type->kind == DEBUG_KIND_TAGGED)
+ && (type->u.knamed->name->mark == info->mark
+ || (type->kind == DEBUG_KIND_TAGGED
+ && type->u.knamed->name != name)))
+ {
+ if (type->kind == DEBUG_KIND_NAMED)
+ return (*fns->typedef_type) (fhandle, type->u.knamed->name->name);
+ else
+ {
+ struct debug_type *real;
+ unsigned int id;
+
+ real = debug_get_real_type ((PTR) info, type);
+ id = 0;
+ if ((real->kind == DEBUG_KIND_STRUCT
+ || real->kind == DEBUG_KIND_UNION
+ || real->kind == DEBUG_KIND_CLASS
+ || real->kind == DEBUG_KIND_UNION_CLASS)
+ && real->u.kclass != NULL)
+ {
+ if (real->u.kclass->id <= info->base_id)
+ {
+ if (! debug_set_class_id (info,
+ type->u.knamed->name->name,
+ real))
+ return false;
+ }
+ id = real->u.kclass->id;
+ }
+
+ return (*fns->tag_type) (fhandle, type->u.knamed->name->name, id,
+ real->kind);
+ }
+ }
+
+ /* Mark the name after we have already looked for a known name, so
+ that we don't just define a type in terms of itself. We need to
+ mark the name here so that a struct containing a pointer to
+ itself will work. */
+ if (name != NULL)
+ name->mark = info->mark;
+
+ tag = NULL;
+ if (name != NULL
+ && type->kind != DEBUG_KIND_NAMED
+ && type->kind != DEBUG_KIND_TAGGED)
+ {
+ assert (name->kind == DEBUG_OBJECT_TAG);
+ tag = name->name;
+ }
+
+ switch (type->kind)
+ {
+ case DEBUG_KIND_ILLEGAL:
+ debug_error ("debug_write_type: illegal type encountered");
+ return false;
+ case DEBUG_KIND_INDIRECT:
+ if (*type->u.kindirect->slot == DEBUG_TYPE_NULL)
+ return (*fns->empty_type) (fhandle);
+ return debug_write_type (info, fns, fhandle, *type->u.kindirect->slot,
+ name);
+ case DEBUG_KIND_VOID:
+ return (*fns->void_type) (fhandle);
+ case DEBUG_KIND_INT:
+ return (*fns->int_type) (fhandle, type->size, type->u.kint);
+ case DEBUG_KIND_FLOAT:
+ return (*fns->float_type) (fhandle, type->size);
+ case DEBUG_KIND_COMPLEX:
+ return (*fns->complex_type) (fhandle, type->size);
+ case DEBUG_KIND_BOOL:
+ return (*fns->bool_type) (fhandle, type->size);
+ case DEBUG_KIND_STRUCT:
+ case DEBUG_KIND_UNION:
+ if (type->u.kclass != NULL)
+ {
+ if (type->u.kclass->id <= info->base_id)
+ {
+ if (! debug_set_class_id (info, tag, type))
+ return false;
+ }
+
+ if (info->mark == type->u.kclass->mark)
+ {
+ /* We are currently outputting this struct, or we have
+ already output it. I don't know if this can happen,
+ but it can happen for a class. */
+ assert (type->u.kclass->id > info->base_id);
+ return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
+ type->kind);
+ }
+ type->u.kclass->mark = info->mark;
+ }
+
+ if (! (*fns->start_struct_type) (fhandle, tag,
+ (type->u.kclass != NULL
+ ? type->u.kclass->id
+ : 0),
+ type->kind == DEBUG_KIND_STRUCT,
+ type->size))
+ return false;
+ if (type->u.kclass != NULL
+ && type->u.kclass->fields != NULL)
+ {
+ for (i = 0; type->u.kclass->fields[i] != NULL; i++)
+ {
+ struct debug_field *f;
+
+ f = type->u.kclass->fields[i];
+ if (! debug_write_type (info, fns, fhandle, f->type,
+ (struct debug_name *) NULL)
+ || ! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos,
+ f->u.f.bitsize, f->visibility))
+ return false;
+ }
+ }
+ return (*fns->end_struct_type) (fhandle);
+ case DEBUG_KIND_CLASS:
+ case DEBUG_KIND_UNION_CLASS:
+ return debug_write_class_type (info, fns, fhandle, type, tag);
+ case DEBUG_KIND_ENUM:
+ if (type->u.kenum == NULL)
+ return (*fns->enum_type) (fhandle, tag, (const char **) NULL,
+ (bfd_signed_vma *) NULL);
+ return (*fns->enum_type) (fhandle, tag, type->u.kenum->names,
+ type->u.kenum->values);
+ case DEBUG_KIND_POINTER:
+ if (! debug_write_type (info, fns, fhandle, type->u.kpointer,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->pointer_type) (fhandle);
+ case DEBUG_KIND_FUNCTION:
+ if (! debug_write_type (info, fns, fhandle,
+ type->u.kfunction->return_type,
+ (struct debug_name *) NULL))
+ return false;
+ if (type->u.kfunction->arg_types == NULL)
+ is = -1;
+ else
+ {
+ for (is = 0; type->u.kfunction->arg_types[is] != NULL; is++)
+ if (! debug_write_type (info, fns, fhandle,
+ type->u.kfunction->arg_types[is],
+ (struct debug_name *) NULL))
+ return false;
+ }
+ return (*fns->function_type) (fhandle, is,
+ type->u.kfunction->varargs);
+ case DEBUG_KIND_REFERENCE:
+ if (! debug_write_type (info, fns, fhandle, type->u.kreference,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->reference_type) (fhandle);
+ case DEBUG_KIND_RANGE:
+ if (! debug_write_type (info, fns, fhandle, type->u.krange->type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->range_type) (fhandle, type->u.krange->lower,
+ type->u.krange->upper);
+ case DEBUG_KIND_ARRAY:
+ if (! debug_write_type (info, fns, fhandle, type->u.karray->element_type,
+ (struct debug_name *) NULL)
+ || ! debug_write_type (info, fns, fhandle,
+ type->u.karray->range_type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->array_type) (fhandle, type->u.karray->lower,
+ type->u.karray->upper,
+ type->u.karray->stringp);
+ case DEBUG_KIND_SET:
+ if (! debug_write_type (info, fns, fhandle, type->u.kset->type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->set_type) (fhandle, type->u.kset->bitstringp);
+ case DEBUG_KIND_OFFSET:
+ if (! debug_write_type (info, fns, fhandle, type->u.koffset->base_type,
+ (struct debug_name *) NULL)
+ || ! debug_write_type (info, fns, fhandle,
+ type->u.koffset->target_type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->offset_type) (fhandle);
+ case DEBUG_KIND_METHOD:
+ if (! debug_write_type (info, fns, fhandle,
+ type->u.kmethod->return_type,
+ (struct debug_name *) NULL))
+ return false;
+ if (type->u.kmethod->arg_types == NULL)
+ is = -1;
+ else
+ {
+ for (is = 0; type->u.kmethod->arg_types[is] != NULL; is++)
+ if (! debug_write_type (info, fns, fhandle,
+ type->u.kmethod->arg_types[is],
+ (struct debug_name *) NULL))
+ return false;
+ }
+ if (type->u.kmethod->domain_type != NULL)
+ {
+ if (! debug_write_type (info, fns, fhandle,
+ type->u.kmethod->domain_type,
+ (struct debug_name *) NULL))
+ return false;
+ }
+ return (*fns->method_type) (fhandle,
+ type->u.kmethod->domain_type != NULL,
+ is,
+ type->u.kmethod->varargs);
+ case DEBUG_KIND_CONST:
+ if (! debug_write_type (info, fns, fhandle, type->u.kconst,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->const_type) (fhandle);
+ case DEBUG_KIND_VOLATILE:
+ if (! debug_write_type (info, fns, fhandle, type->u.kvolatile,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->volatile_type) (fhandle);
+ case DEBUG_KIND_NAMED:
+ return debug_write_type (info, fns, fhandle, type->u.knamed->type,
+ (struct debug_name *) NULL);
+ case DEBUG_KIND_TAGGED:
+ return debug_write_type (info, fns, fhandle, type->u.knamed->type,
+ type->u.knamed->name);
+ default:
+ abort ();
+ return false;
+ }
+}
+
+/* Write out a class type. */
+
+static boolean
+debug_write_class_type (info, fns, fhandle, type, tag)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ struct debug_type *type;
+ const char *tag;
+{
+ unsigned int i;
+ unsigned int id;
+ struct debug_type *vptrbase;
+
+ if (type->u.kclass == NULL)
+ {
+ id = 0;
+ vptrbase = NULL;
+ }
+ else
+ {
+ if (type->u.kclass->id <= info->base_id)
+ {
+ if (! debug_set_class_id (info, tag, type))
+ return false;
+ }
+
+ if (info->mark == type->u.kclass->mark)
+ {
+ /* We are currently outputting this class, or we have
+ already output it. This can happen when there are
+ methods for an anonymous class. */
+ assert (type->u.kclass->id > info->base_id);
+ return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
+ type->kind);
+ }
+ type->u.kclass->mark = info->mark;
+ id = type->u.kclass->id;
+
+ vptrbase = type->u.kclass->vptrbase;
+ if (vptrbase != NULL && vptrbase != type)
+ {
+ if (! debug_write_type (info, fns, fhandle, vptrbase,
+ (struct debug_name *) NULL))
+ return false;
+ }
+ }
+
+ if (! (*fns->start_class_type) (fhandle, tag, id,
+ type->kind == DEBUG_KIND_CLASS,
+ type->size,
+ vptrbase != NULL,
+ vptrbase == type))
+ return false;
+
+ if (type->u.kclass != NULL)
+ {
+ if (type->u.kclass->fields != NULL)
+ {
+ for (i = 0; type->u.kclass->fields[i] != NULL; i++)
+ {
+ struct debug_field *f;
+
+ f = type->u.kclass->fields[i];
+ if (! debug_write_type (info, fns, fhandle, f->type,
+ (struct debug_name *) NULL))
+ return false;
+ if (f->static_member)
+ {
+ if (! (*fns->class_static_member) (fhandle, f->name,
+ f->u.s.physname,
+ f->visibility))
+ return false;
+ }
+ else
+ {
+ if (! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos,
+ f->u.f.bitsize, f->visibility))
+ return false;
+ }
+ }
+ }
+
+ if (type->u.kclass->baseclasses != NULL)
+ {
+ for (i = 0; type->u.kclass->baseclasses[i] != NULL; i++)
+ {
+ struct debug_baseclass *b;
+
+ b = type->u.kclass->baseclasses[i];
+ if (! debug_write_type (info, fns, fhandle, b->type,
+ (struct debug_name *) NULL))
+ return false;
+ if (! (*fns->class_baseclass) (fhandle, b->bitpos, b->virtual,
+ b->visibility))
+ return false;
+ }
+ }
+
+ if (type->u.kclass->methods != NULL)
+ {
+ for (i = 0; type->u.kclass->methods[i] != NULL; i++)
+ {
+ struct debug_method *m;
+ unsigned int j;
+
+ m = type->u.kclass->methods[i];
+ if (! (*fns->class_start_method) (fhandle, m->name))
+ return false;
+ for (j = 0; m->variants[j] != NULL; j++)
+ {
+ struct debug_method_variant *v;
+
+ v = m->variants[j];
+ if (v->context != NULL)
+ {
+ if (! debug_write_type (info, fns, fhandle, v->context,
+ (struct debug_name *) NULL))
+ return false;
+ }
+ if (! debug_write_type (info, fns, fhandle, v->type,
+ (struct debug_name *) NULL))
+ return false;
+ if (v->voffset != VOFFSET_STATIC_METHOD)
+ {
+ if (! (*fns->class_method_variant) (fhandle, v->physname,
+ v->visibility,
+ v->constp,
+ v->volatilep,
+ v->voffset,
+ v->context != NULL))
+ return false;
+ }
+ else
+ {
+ if (! (*fns->class_static_method_variant) (fhandle,
+ v->physname,
+ v->visibility,
+ v->constp,
+ v->volatilep))
+ return false;
+ }
+ }
+ if (! (*fns->class_end_method) (fhandle))
+ return false;
+ }
+ }
+ }
+
+ return (*fns->end_class_type) (fhandle);
+}
+
+/* Write out information for a function. */
+
+static boolean
+debug_write_function (info, fns, fhandle, name, linkage, function)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ const char *name;
+ enum debug_object_linkage linkage;
+ struct debug_function *function;
+{
+ struct debug_parameter *p;
+ struct debug_block *b;
+
+ if (! debug_write_linenos (info, fns, fhandle, function->blocks->start))
+ return false;
+
+ if (! debug_write_type (info, fns, fhandle, function->return_type,
+ (struct debug_name *) NULL))
+ return false;
+
+ if (! (*fns->start_function) (fhandle, name,
+ linkage == DEBUG_LINKAGE_GLOBAL))
+ return false;
+
+ for (p = function->parameters; p != NULL; p = p->next)
+ {
+ if (! debug_write_type (info, fns, fhandle, p->type,
+ (struct debug_name *) NULL)
+ || ! (*fns->function_parameter) (fhandle, p->name, p->kind, p->val))
+ return false;
+ }
+
+ for (b = function->blocks; b != NULL; b = b->next)
+ {
+ if (! debug_write_block (info, fns, fhandle, b))
+ return false;
+ }
+
+ return (*fns->end_function) (fhandle);
+}
+
+/* Write out information for a block. */
+
+static boolean
+debug_write_block (info, fns, fhandle, block)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ struct debug_block *block;
+{
+ struct debug_name *n;
+ struct debug_block *b;
+
+ if (! debug_write_linenos (info, fns, fhandle, block->start))
+ return false;
+
+ /* I can't see any point to writing out a block with no local
+ variables, so we don't bother, except for the top level block. */
+ if (block->locals != NULL || block->parent == NULL)
+ {
+ if (! (*fns->start_block) (fhandle, block->start))
+ return false;
+ }
+
+ if (block->locals != NULL)
+ {
+ for (n = block->locals->list; n != NULL; n = n->next)
+ {
+ if (! debug_write_name (info, fns, fhandle, n))
+ return false;
+ }
+ }
+
+ for (b = block->children; b != NULL; b = b->next)
+ {
+ if (! debug_write_block (info, fns, fhandle, b))
+ return false;
+ }
+
+ if (! debug_write_linenos (info, fns, fhandle, block->end))
+ return false;
+
+ if (block->locals != NULL || block->parent == NULL)
+ {
+ if (! (*fns->end_block) (fhandle, block->end))
+ return false;
+ }
+
+ return true;
+}
+
+/* Write out line number information up to ADDRESS. */
+
+static boolean
+debug_write_linenos (info, fns, fhandle, address)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ bfd_vma address;
+{
+ while (info->current_write_lineno != NULL)
+ {
+ struct debug_lineno *l;
+
+ l = info->current_write_lineno;
+
+ while (info->current_write_lineno_index < DEBUG_LINENO_COUNT)
+ {
+ if (l->linenos[info->current_write_lineno_index]
+ == (unsigned long) -1)
+ break;
+
+ if (l->addrs[info->current_write_lineno_index] >= address)
+ return true;
+
+ if (! (*fns->lineno) (fhandle, l->file->filename,
+ l->linenos[info->current_write_lineno_index],
+ l->addrs[info->current_write_lineno_index]))
+ return false;
+
+ ++info->current_write_lineno_index;
+ }
+
+ info->current_write_lineno = l->next;
+ info->current_write_lineno_index = 0;
+ }
+
+ return true;
+}
+
+/* Get the ID number for a class. If during the same call to
+ debug_write we find a struct with the same definition with the same
+ name, we use the same ID. This type of things happens because the
+ same struct will be defined by multiple compilation units. */
+
+static boolean
+debug_set_class_id (info, tag, type)
+ struct debug_handle *info;
+ const char *tag;
+ struct debug_type *type;
+{
+ struct debug_class_type *c;
+ struct debug_class_id *l;
+
+ assert (type->kind == DEBUG_KIND_STRUCT
+ || type->kind == DEBUG_KIND_UNION
+ || type->kind == DEBUG_KIND_CLASS
+ || type->kind == DEBUG_KIND_UNION_CLASS);
+
+ c = type->u.kclass;
+
+ if (c->id > info->base_id)
+ return true;
+
+ for (l = info->id_list; l != NULL; l = l->next)
+ {
+ if (l->type->kind != type->kind)
+ continue;
+
+ if (tag == NULL)
+ {
+ if (l->tag != NULL)
+ continue;
+ }
+ else
+ {
+ if (l->tag == NULL
+ || l->tag[0] != tag[0]
+ || strcmp (l->tag, tag) != 0)
+ continue;
+ }
+
+ if (debug_type_samep (info, l->type, type))
+ {
+ c->id = l->type->u.kclass->id;
+ return true;
+ }
+ }
+
+ /* There are no identical types. Use a new ID, and add it to the
+ list. */
+ ++info->class_id;
+ c->id = info->class_id;
+
+ l = (struct debug_class_id *) xmalloc (sizeof *l);
+ memset (l, 0, sizeof *l);
+
+ l->type = type;
+ l->tag = tag;
+
+ l->next = info->id_list;
+ info->id_list = l;
+
+ return true;
+}
+
+/* See if two types are the same. At this point, we don't care about
+ tags and the like. */
+
+static boolean
+debug_type_samep (info, t1, t2)
+ struct debug_handle *info;
+ struct debug_type *t1;
+ struct debug_type *t2;
+{
+ struct debug_type_compare_list *l;
+ struct debug_type_compare_list top;
+ boolean ret;
+
+ while (t1->kind == DEBUG_KIND_INDIRECT)
+ {
+ t1 = *t1->u.kindirect->slot;
+ if (t1 == NULL)
+ return false;
+ }
+ while (t2->kind == DEBUG_KIND_INDIRECT)
+ {
+ t2 = *t2->u.kindirect->slot;
+ if (t2 == NULL)
+ return false;
+ }
+
+ if (t1 == t2)
+ return true;
+
+ /* As a special case, permit a typedef to match a tag, since C++
+ debugging output will sometimes add a typedef where C debugging
+ output will not. */
+ if (t1->kind == DEBUG_KIND_NAMED
+ && t2->kind == DEBUG_KIND_TAGGED)
+ return debug_type_samep (info, t1->u.knamed->type, t2);
+ else if (t1->kind == DEBUG_KIND_TAGGED
+ && t2->kind == DEBUG_KIND_NAMED)
+ return debug_type_samep (info, t1, t2->u.knamed->type);
+
+ if (t1->kind != t2->kind
+ || t1->size != t2->size)
+ return false;
+
+ /* Get rid of the trivial cases first. */
+ switch (t1->kind)
+ {
+ default:
+ break;
+ case DEBUG_KIND_VOID:
+ case DEBUG_KIND_FLOAT:
+ case DEBUG_KIND_COMPLEX:
+ case DEBUG_KIND_BOOL:
+ return true;
+ case DEBUG_KIND_INT:
+ return t1->u.kint == t2->u.kint;
+ }
+
+ /* We have to avoid an infinite recursion. We do this by keeping a
+ list of types which we are comparing. We just keep the list on
+ the stack. If we encounter a pair of types we are currently
+ comparing, we just assume that they are equal. */
+ for (l = info->compare_list; l != NULL; l = l->next)
+ {
+ if (l->t1 == t1 && l->t2 == t2)
+ return true;
+ }
+
+ top.t1 = t1;
+ top.t2 = t2;
+ top.next = info->compare_list;
+ info->compare_list = &top;
+
+ switch (t1->kind)
+ {
+ default:
+ abort ();
+ ret = false;
+ break;
+
+ case DEBUG_KIND_STRUCT:
+ case DEBUG_KIND_UNION:
+ case DEBUG_KIND_CLASS:
+ case DEBUG_KIND_UNION_CLASS:
+ if (t1->u.kclass == NULL)
+ ret = t2->u.kclass == NULL;
+ else if (t2->u.kclass == NULL)
+ ret = false;
+ else if (t1->u.kclass->id > info->base_id
+ && t1->u.kclass->id == t2->u.kclass->id)
+ ret = true;
+ else
+ ret = debug_class_type_samep (info, t1, t2);
+ break;
+
+ case DEBUG_KIND_ENUM:
+ if (t1->u.kenum == NULL)
+ ret = t2->u.kenum == NULL;
+ else if (t2->u.kenum == NULL)
+ ret = false;
+ else
+ {
+ const char **pn1, **pn2;
+ bfd_signed_vma *pv1, *pv2;
+
+ pn1 = t1->u.kenum->names;
+ pn2 = t2->u.kenum->names;
+ pv1 = t1->u.kenum->values;
+ pv2 = t2->u.kenum->values;
+ while (*pn1 != NULL && *pn2 != NULL)
+ {
+ if (**pn1 != **pn2
+ || *pv1 != *pv2
+ || strcmp (*pn1, *pn2) != 0)
+ break;
+ ++pn1;
+ ++pn2;
+ ++pv1;
+ ++pv2;
+ }
+ ret = *pn1 == NULL && *pn2 == NULL;
+ }
+ break;
+
+ case DEBUG_KIND_POINTER:
+ ret = debug_type_samep (info, t1->u.kpointer, t2->u.kpointer);
+ break;
+
+ case DEBUG_KIND_FUNCTION:
+ if (t1->u.kfunction->varargs != t2->u.kfunction->varargs
+ || ! debug_type_samep (info, t1->u.kfunction->return_type,
+ t2->u.kfunction->return_type)
+ || ((t1->u.kfunction->arg_types == NULL)
+ != (t2->u.kfunction->arg_types == NULL)))
+ ret = false;
+ else if (t1->u.kfunction->arg_types == NULL)
+ ret = true;
+ else
+ {
+ struct debug_type **a1, **a2;
+
+ a1 = t1->u.kfunction->arg_types;
+ a2 = t2->u.kfunction->arg_types;
+ while (*a1 != NULL && *a2 != NULL)
+ if (! debug_type_samep (info, *a1, *a2))
+ break;
+ ret = *a1 == NULL && *a2 == NULL;
+ }
+ break;
+
+ case DEBUG_KIND_REFERENCE:
+ ret = debug_type_samep (info, t1->u.kreference, t2->u.kreference);
+ break;
+
+ case DEBUG_KIND_RANGE:
+ ret = (t1->u.krange->lower == t2->u.krange->lower
+ && t1->u.krange->upper == t2->u.krange->upper
+ && debug_type_samep (info, t1->u.krange->type,
+ t2->u.krange->type));
+
+ case DEBUG_KIND_ARRAY:
+ ret = (t1->u.karray->lower == t2->u.karray->lower
+ && t1->u.karray->upper == t2->u.karray->upper
+ && t1->u.karray->stringp == t2->u.karray->stringp
+ && debug_type_samep (info, t1->u.karray->element_type,
+ t2->u.karray->element_type));
+ break;
+
+ case DEBUG_KIND_SET:
+ ret = (t1->u.kset->bitstringp == t2->u.kset->bitstringp
+ && debug_type_samep (info, t1->u.kset->type, t2->u.kset->type));
+ break;
+
+ case DEBUG_KIND_OFFSET:
+ ret = (debug_type_samep (info, t1->u.koffset->base_type,
+ t2->u.koffset->base_type)
+ && debug_type_samep (info, t1->u.koffset->target_type,
+ t2->u.koffset->target_type));
+ break;
+
+ case DEBUG_KIND_METHOD:
+ if (t1->u.kmethod->varargs != t2->u.kmethod->varargs
+ || ! debug_type_samep (info, t1->u.kmethod->return_type,
+ t2->u.kmethod->return_type)
+ || ! debug_type_samep (info, t1->u.kmethod->domain_type,
+ t2->u.kmethod->domain_type)
+ || ((t1->u.kmethod->arg_types == NULL)
+ != (t2->u.kmethod->arg_types == NULL)))
+ ret = false;
+ else if (t1->u.kmethod->arg_types == NULL)
+ ret = true;
+ else
+ {
+ struct debug_type **a1, **a2;
+
+ a1 = t1->u.kmethod->arg_types;
+ a2 = t2->u.kmethod->arg_types;
+ while (*a1 != NULL && *a2 != NULL)
+ if (! debug_type_samep (info, *a1, *a2))
+ break;
+ ret = *a1 == NULL && *a2 == NULL;
+ }
+ break;
+
+ case DEBUG_KIND_CONST:
+ ret = debug_type_samep (info, t1->u.kconst, t2->u.kconst);
+ break;
+
+ case DEBUG_KIND_VOLATILE:
+ ret = debug_type_samep (info, t1->u.kvolatile, t2->u.kvolatile);
+ break;
+
+ case DEBUG_KIND_NAMED:
+ case DEBUG_KIND_TAGGED:
+ ret = (strcmp (t1->u.knamed->name->name, t2->u.knamed->name->name) == 0
+ && debug_type_samep (info, t1->u.knamed->type,
+ t2->u.knamed->type));
+ break;
+ }
+
+ info->compare_list = top.next;
+
+ return ret;
+}
+
+/* See if two classes are the same. This is a subroutine of
+ debug_type_samep. */
+
+static boolean
+debug_class_type_samep (info, t1, t2)
+ struct debug_handle *info;
+ struct debug_type *t1;
+ struct debug_type *t2;
+{
+ struct debug_class_type *c1, *c2;
+
+ c1 = t1->u.kclass;
+ c2 = t2->u.kclass;
+
+ if ((c1->fields == NULL) != (c2->fields == NULL)
+ || (c1->baseclasses == NULL) != (c2->baseclasses == NULL)
+ || (c1->methods == NULL) != (c2->methods == NULL)
+ || (c1->vptrbase == NULL) != (c2->vptrbase == NULL))
+ return false;
+
+ if (c1->fields != NULL)
+ {
+ struct debug_field **pf1, **pf2;
+
+ for (pf1 = c1->fields, pf2 = c2->fields;
+ *pf1 != NULL && *pf2 != NULL;
+ pf1++, pf2++)
+ {
+ struct debug_field *f1, *f2;
+
+ f1 = *pf1;
+ f2 = *pf2;
+ if (f1->name[0] != f2->name[0]
+ || f1->visibility != f2->visibility
+ || f1->static_member != f2->static_member)
+ return false;
+ if (f1->static_member)
+ {
+ if (strcmp (f1->u.s.physname, f2->u.s.physname) != 0)
+ return false;
+ }
+ else
+ {
+ if (f1->u.f.bitpos != f2->u.f.bitpos
+ || f1->u.f.bitsize != f2->u.f.bitsize)
+ return false;
+ }
+ /* We do the checks which require function calls last. We
+ don't require that the types of fields have the same
+ names, since that sometimes fails in the presence of
+ typedefs and we really don't care. */
+ if (strcmp (f1->name, f2->name) != 0
+ || ! debug_type_samep (info,
+ debug_get_real_type ((PTR) info,
+ f1->type),
+ debug_get_real_type ((PTR) info,
+ f2->type)))
+ return false;
+ }
+ if (*pf1 != NULL || *pf2 != NULL)
+ return false;
+ }
+
+ if (c1->vptrbase != NULL)
+ {
+ if (! debug_type_samep (info, c1->vptrbase, c2->vptrbase))
+ return false;
+ }
+
+ if (c1->baseclasses != NULL)
+ {
+ struct debug_baseclass **pb1, **pb2;
+
+ for (pb1 = c1->baseclasses, pb2 = c2->baseclasses;
+ *pb1 != NULL && *pb2 != NULL;
+ ++pb1, ++pb2)
+ {
+ struct debug_baseclass *b1, *b2;
+
+ b1 = *pb1;
+ b2 = *pb2;
+ if (b1->bitpos != b2->bitpos
+ || b1->virtual != b2->virtual
+ || b1->visibility != b2->visibility
+ || ! debug_type_samep (info, b1->type, b2->type))
+ return false;
+ }
+ if (*pb1 != NULL || *pb2 != NULL)
+ return false;
+ }
+
+ if (c1->methods != NULL)
+ {
+ struct debug_method **pm1, **pm2;
+
+ for (pm1 = c1->methods, pm2 = c2->methods;
+ *pm1 != NULL && *pm2 != NULL;
+ ++pm1, ++pm2)
+ {
+ struct debug_method *m1, *m2;
+
+ m1 = *pm1;
+ m2 = *pm2;
+ if (m1->name[0] != m2->name[0]
+ || strcmp (m1->name, m2->name) != 0
+ || (m1->variants == NULL) != (m2->variants == NULL))
+ return false;
+ if (m1->variants == NULL)
+ {
+ struct debug_method_variant **pv1, **pv2;
+
+ for (pv1 = m1->variants, pv2 = m2->variants;
+ *pv1 != NULL && *pv2 != NULL;
+ ++pv1, ++pv2)
+ {
+ struct debug_method_variant *v1, *v2;
+
+ v1 = *pv1;
+ v2 = *pv2;
+ if (v1->physname[0] != v2->physname[0]
+ || v1->visibility != v2->visibility
+ || v1->constp != v2->constp
+ || v1->volatilep != v2->volatilep
+ || v1->voffset != v2->voffset
+ || (v1->context == NULL) != (v2->context == NULL)
+ || strcmp (v1->physname, v2->physname) != 0
+ || ! debug_type_samep (info, v1->type, v2->type))
+ return false;
+ if (v1->context != NULL)
+ {
+ if (! debug_type_samep (info, v1->context,
+ v2->context))
+ return false;
+ }
+ }
+ if (*pv1 != NULL || *pv2 != NULL)
+ return false;
+ }
+ }
+ if (*pm1 != NULL || *pm2 != NULL)
+ return false;
+ }
+
+ return true;
+}
diff --git a/gnu/usr.bin/binutils/binutils/debug.h b/gnu/usr.bin/binutils/binutils/debug.h
new file mode 100644
index 00000000000..1b890b234f1
--- /dev/null
+++ b/gnu/usr.bin/binutils/binutils/debug.h
@@ -0,0 +1,798 @@
+/* debug.h -- Describe generic debugging information.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ 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. */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+/* This header file describes a generic debugging information format.
+ We may eventually have readers which convert different formats into
+ this generic format, and writers which write it out. The initial
+ impetus for this was writing a convertor from stabs to HP IEEE-695
+ debugging format. */
+
+/* Different kinds of types. */
+
+enum debug_type_kind
+{
+ /* Not used. */
+ DEBUG_KIND_ILLEGAL,
+ /* Indirect via a pointer. */
+ DEBUG_KIND_INDIRECT,
+ /* Void. */
+ DEBUG_KIND_VOID,
+ /* Integer. */
+ DEBUG_KIND_INT,
+ /* Floating point. */
+ DEBUG_KIND_FLOAT,
+ /* Complex. */
+ DEBUG_KIND_COMPLEX,
+ /* Boolean. */
+ DEBUG_KIND_BOOL,
+ /* Struct. */
+ DEBUG_KIND_STRUCT,
+ /* Union. */
+ DEBUG_KIND_UNION,
+ /* Class. */
+ DEBUG_KIND_CLASS,
+ /* Union class (can this really happen?). */
+ DEBUG_KIND_UNION_CLASS,
+ /* Enumeration type. */
+ DEBUG_KIND_ENUM,
+ /* Pointer. */
+ DEBUG_KIND_POINTER,
+ /* Function. */
+ DEBUG_KIND_FUNCTION,
+ /* Reference. */
+ DEBUG_KIND_REFERENCE,
+ /* Range. */
+ DEBUG_KIND_RANGE,
+ /* Array. */
+ DEBUG_KIND_ARRAY,
+ /* Set. */
+ DEBUG_KIND_SET,
+ /* Based pointer. */
+ DEBUG_KIND_OFFSET,
+ /* Method. */
+ DEBUG_KIND_METHOD,
+ /* Const qualified type. */
+ DEBUG_KIND_CONST,
+ /* Volatile qualified type. */
+ DEBUG_KIND_VOLATILE,
+ /* Named type. */
+ DEBUG_KIND_NAMED,
+ /* Tagged type. */
+ DEBUG_KIND_TAGGED
+};
+
+/* Different kinds of variables. */
+
+enum debug_var_kind
+{
+ /* Not used. */
+ DEBUG_VAR_ILLEGAL,
+ /* A global variable. */
+ DEBUG_GLOBAL,
+ /* A static variable. */
+ DEBUG_STATIC,
+ /* A local static variable. */
+ DEBUG_LOCAL_STATIC,
+ /* A local variable. */
+ DEBUG_LOCAL,
+ /* A register variable. */
+ DEBUG_REGISTER
+};
+
+/* Different kinds of function parameters. */
+
+enum debug_parm_kind
+{
+ /* Not used. */
+ DEBUG_PARM_ILLEGAL,
+ /* A stack based parameter. */
+ DEBUG_PARM_STACK,
+ /* A register parameter. */
+ DEBUG_PARM_REG,
+ /* A stack based reference parameter. */
+ DEBUG_PARM_REFERENCE,
+ /* A register reference parameter. */
+ DEBUG_PARM_REF_REG
+};
+
+/* Different kinds of visibility. */
+
+enum debug_visibility
+{
+ /* A public field (e.g., a field in a C struct). */
+ DEBUG_VISIBILITY_PUBLIC,
+ /* A protected field. */
+ DEBUG_VISIBILITY_PROTECTED,
+ /* A private field. */
+ DEBUG_VISIBILITY_PRIVATE,
+ /* A field which should be ignored. */
+ DEBUG_VISIBILITY_IGNORE
+};
+
+/* A type. */
+
+typedef struct debug_type *debug_type;
+
+#define DEBUG_TYPE_NULL ((debug_type) NULL)
+
+/* A field in a struct or union. */
+
+typedef struct debug_field *debug_field;
+
+#define DEBUG_FIELD_NULL ((debug_field) NULL)
+
+/* A base class for an object. */
+
+typedef struct debug_baseclass *debug_baseclass;
+
+#define DEBUG_BASECLASS_NULL ((debug_baseclass) NULL)
+
+/* A method of an object. */
+
+typedef struct debug_method *debug_method;
+
+#define DEBUG_METHOD_NULL ((debug_method) NULL)
+
+/* The arguments to a method function of an object. These indicate
+ which method to run. */
+
+typedef struct debug_method_variant *debug_method_variant;
+
+#define DEBUG_METHOD_VARIANT_NULL ((debug_method_variant) NULL)
+
+/* This structure is passed to debug_write. It holds function
+ pointers that debug_write will call based on the accumulated
+ debugging information. */
+
+struct debug_write_fns
+{
+ /* This is called at the start of each new compilation unit with the
+ name of the main file in the new unit. */
+ boolean (*start_compilation_unit) PARAMS ((PTR, const char *));
+
+ /* This is called at the start of each source file within a
+ compilation unit, before outputting any global information for
+ that file. The argument is the name of the file. */
+ boolean (*start_source) PARAMS ((PTR, const char *));
+
+ /* Each writer must keep a stack of types. */
+
+ /* Push an empty type onto the type stack. This type can appear if
+ there is a reference to a type which is never defined. */
+ boolean (*empty_type) PARAMS ((PTR));
+
+ /* Push a void type onto the type stack. */
+ boolean (*void_type) PARAMS ((PTR));
+
+ /* Push an integer type onto the type stack, given the size and
+ whether it is unsigned. */
+ boolean (*int_type) PARAMS ((PTR, unsigned int, boolean));
+
+ /* Push a floating type onto the type stack, given the size. */
+ boolean (*float_type) PARAMS ((PTR, unsigned int));
+
+ /* Push a complex type onto the type stack, given the size. */
+ boolean (*complex_type) PARAMS ((PTR, unsigned int));
+
+ /* Push a boolean type onto the type stack, given the size. */
+ boolean (*bool_type) PARAMS ((PTR, unsigned int));
+
+ /* Push an enum type onto the type stack, given the tag, a NULL
+ terminated array of names and the associated values. If there is
+ no tag, the tag argument will be NULL. If this is an undefined
+ enum, the names and values arguments will be NULL. */
+ boolean (*enum_type) PARAMS ((PTR, const char *, const char **,
+ bfd_signed_vma *));
+
+ /* Pop the top type on the type stack, and push a pointer to that
+ type onto the type stack. */
+ boolean (*pointer_type) PARAMS ((PTR));
+
+ /* Push a function type onto the type stack. The second argument
+ indicates the number of argument types that have been pushed onto
+ the stack. If the number of argument types is passed as -1, then
+ the argument types of the function are unknown, and no types have
+ been pushed onto the stack. The third argument is true if the
+ function takes a variable number of arguments. The return type
+ of the function is pushed onto the type stack below the argument
+ types, if any. */
+ boolean (*function_type) PARAMS ((PTR, int, boolean));
+
+ /* Pop the top type on the type stack, and push a reference to that
+ type onto the type stack. */
+ boolean (*reference_type) PARAMS ((PTR));
+
+ /* Pop the top type on the type stack, and push a range of that type
+ with the given lower and upper bounds onto the type stack. */
+ boolean (*range_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+
+ /* Push an array type onto the type stack. The top type on the type
+ stack is the range, and the next type on the type stack is the
+ element type. These should be popped before the array type is
+ pushed. The arguments are the lower bound, the upper bound, and
+ whether the array is a string. */
+ boolean (*array_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma,
+ boolean));
+
+ /* Pop the top type on the type stack, and push a set of that type
+ onto the type stack. The argument indicates whether this set is
+ a bitstring. */
+ boolean (*set_type) PARAMS ((PTR, boolean));
+
+ /* Push an offset type onto the type stack. The top type on the
+ type stack is the target type, and the next type on the type
+ stack is the base type. These should be popped before the offset
+ type is pushed. */
+ boolean (*offset_type) PARAMS ((PTR));
+
+ /* Push a method type onto the type stack. If the second argument
+ is true, the top type on the stack is the class to which the
+ method belongs; otherwise, the class must be determined by the
+ class to which the method is attached. The third argument is the
+ number of argument types; these are pushed onto the type stack in
+ reverse order (the first type popped is the last argument to the
+ method). A value of -1 for the third argument means that no
+ argument information is available. The fourth argument is true
+ if the function takes a variable number of arguments. The next
+ type on the type stack below the domain and the argument types is
+ the return type of the method. All these types must be popped,
+ and then the method type must be pushed. */
+ boolean (*method_type) PARAMS ((PTR, boolean, int, boolean));
+
+ /* Pop the top type off the type stack, and push a const qualified
+ version of that type onto the type stack. */
+ boolean (*const_type) PARAMS ((PTR));
+
+ /* Pop the top type off the type stack, and push a volatile
+ qualified version of that type onto the type stack. */
+ boolean (*volatile_type) PARAMS ((PTR));
+
+ /* Start building a struct. This is followed by calls to the
+ struct_field function, and finished by a call to the
+ end_struct_type function. The second argument is the tag; this
+ will be NULL if there isn't one. If the second argument is NULL,
+ the third argument is a constant identifying this struct for use
+ with tag_type. The fourth argument is true for a struct, false
+ for a union. The fifth argument is the size. If this is an
+ undefined struct or union, the size will be 0 and struct_field
+ will not be called before end_struct_type is called. */
+ boolean (*start_struct_type) PARAMS ((PTR, const char *, unsigned int,
+ boolean, unsigned int));
+
+ /* Add a field to the struct type currently being built. The type
+ of the field should be popped off the type stack. The arguments
+ are the name, the bit position, the bit size (may be zero if the
+ field is not packed), and the visibility. */
+ boolean (*struct_field) PARAMS ((PTR, const char *, bfd_vma, bfd_vma,
+ enum debug_visibility));
+
+ /* Finish building a struct, and push it onto the type stack. */
+ boolean (*end_struct_type) PARAMS ((PTR));
+
+ /* Start building a class. This is followed by calls to several
+ functions: struct_field, class_static_member, class_baseclass,
+ class_start_method, class_method_variant,
+ class_static_method_variant, and class_end_method. The class is
+ finished by a call to end_class_type. The first five arguments
+ are the same as for start_struct_type. The sixth argument is
+ true if there is a virtual function table; if there is, the
+ seventh argument is true if the virtual function table can be
+ found in the type itself, and is false if the type of the object
+ holding the virtual function table should be popped from the type
+ stack. */
+ boolean (*start_class_type) PARAMS ((PTR, const char *, unsigned int,
+ boolean, unsigned int, boolean,
+ boolean));
+
+ /* Add a static member to the class currently being built. The
+ arguments are the field name, the physical name, and the
+ visibility. The type must be popped off the type stack. */
+ boolean (*class_static_member) PARAMS ((PTR, const char *, const char *,
+ enum debug_visibility));
+
+ /* Add a baseclass to the class currently being built. The type of
+ the baseclass must be popped off the type stack. The arguments
+ are the bit position, whether the class is virtual, and the
+ visibility. */
+ boolean (*class_baseclass) PARAMS ((PTR, bfd_vma, boolean,
+ enum debug_visibility));
+
+ /* Start adding a method to the class currently being built. This
+ is followed by calls to class_method_variant and
+ class_static_method_variant to describe different variants of the
+ method which take different arguments. The method is finished
+ with a call to class_end_method. The argument is the method
+ name. */
+ boolean (*class_start_method) PARAMS ((PTR, const char *));
+
+ /* Describe a variant to the class method currently being built.
+ The type of the variant must be popped off the type stack. The
+ second argument is the physical name of the function. The
+ following arguments are the visibility, whether the variant is
+ const, whether the variant is volatile, the offset in the virtual
+ function table, and whether the context is on the type stack
+ (below the variant type). */
+ boolean (*class_method_variant) PARAMS ((PTR, const char *,
+ enum debug_visibility,
+ boolean, boolean,
+ bfd_vma, boolean));
+
+ /* Describe a static variant to the class method currently being
+ built. The arguments are the same as for class_method_variant,
+ except that the last two arguments are omitted. The type of the
+ variant must be popped off the type stack. */
+ boolean (*class_static_method_variant) PARAMS ((PTR, const char *,
+ enum debug_visibility,
+ boolean, boolean));
+
+ /* Finish describing a class method. */
+ boolean (*class_end_method) PARAMS ((PTR));
+
+ /* Finish describing a class, and push it onto the type stack. */
+ boolean (*end_class_type) PARAMS ((PTR));
+
+ /* Push a type on the stack which was given a name by an earlier
+ call to typdef. */
+ boolean (*typedef_type) PARAMS ((PTR, const char *));
+
+ /* Push a tagged type on the stack which was defined earlier. If
+ the second argument is not NULL, the type was defined by a call
+ to tag. If the second argument is NULL, the type was defined by
+ a call to start_struct_type or start_class_type with a tag of
+ NULL and the number of the third argument. Either way, the
+ fourth argument is the tag kind. Note that this may be called
+ for a struct (class) being defined, in between the call to
+ start_struct_type (start_class_type) and the call to
+ end_struct_type (end_class_type). */
+ boolean (*tag_type) PARAMS ((PTR, const char *, unsigned int,
+ enum debug_type_kind));
+
+ /* Pop the type stack, and typedef it to the given name. */
+ boolean (*typdef) PARAMS ((PTR, const char *));
+
+ /* Pop the type stack, and declare it as a tagged struct or union or
+ enum or whatever. The tag passed down here is redundant, since
+ was also passed when enum_type, start_struct_type, or
+ start_class_type was called. */
+ boolean (*tag) PARAMS ((PTR, const char *));
+
+ /* This is called to record a named integer constant. */
+ boolean (*int_constant) PARAMS ((PTR, const char *, bfd_vma));
+
+ /* This is called to record a named floating point constant. */
+ boolean (*float_constant) PARAMS ((PTR, const char *, double));
+
+ /* This is called to record a typed integer constant. The type is
+ popped off the type stack. */
+ boolean (*typed_constant) PARAMS ((PTR, const char *, bfd_vma));
+
+ /* This is called to record a variable. The type is popped off the
+ type stack. */
+ boolean (*variable) PARAMS ((PTR, const char *, enum debug_var_kind,
+ bfd_vma));
+
+ /* Start writing out a function. The return type must be popped off
+ the stack. The boolean is true if the function is global. This
+ is followed by calls to function_parameter, followed by block
+ information. */
+ boolean (*start_function) PARAMS ((PTR, const char *, boolean));
+
+ /* Record a function parameter for the current function. The type
+ must be popped off the stack. */
+ boolean (*function_parameter) PARAMS ((PTR, const char *,
+ enum debug_parm_kind, bfd_vma));
+
+ /* Start writing out a block. There is at least one top level block
+ per function. Blocks may be nested. The argument is the
+ starting address of the block. */
+ boolean (*start_block) PARAMS ((PTR, bfd_vma));
+
+ /* Finish writing out a block. The argument is the ending address
+ of the block. */
+ boolean (*end_block) PARAMS ((PTR, bfd_vma));
+
+ /* Finish writing out a function. */
+ boolean (*end_function) PARAMS ((PTR));
+
+ /* Record line number information for the current compilation unit. */
+ boolean (*lineno) PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+};
+
+/* Exported functions. */
+
+/* The first argument to most of these functions is a handle. This
+ handle is returned by the debug_init function. The purpose of the
+ handle is to permit the debugging routines to not use static
+ variables, and hence to be reentrant. This would be useful for a
+ program which wanted to handle two executables simultaneously. */
+
+/* Return a debugging handle. */
+
+extern PTR debug_init PARAMS ((void));
+
+/* Set the source filename. This implicitly starts a new compilation
+ unit. */
+
+extern boolean debug_set_filename PARAMS ((PTR, const char *));
+
+/* Change source files to the given file name. This is used for
+ include files in a single compilation unit. */
+
+extern boolean debug_start_source PARAMS ((PTR, const char *));
+
+/* Record a function definition. This implicitly starts a function
+ block. The debug_type argument is the type of the return value.
+ The boolean indicates whether the function is globally visible.
+ The bfd_vma is the address of the start of the function. Currently
+ the parameter types are specified by calls to
+ debug_record_parameter. */
+
+extern boolean debug_record_function
+ PARAMS ((PTR, const char *, debug_type, boolean, bfd_vma));
+
+/* Record a parameter for the current function. */
+
+extern boolean debug_record_parameter
+ PARAMS ((PTR, const char *, debug_type, enum debug_parm_kind, bfd_vma));
+
+/* End a function definition. The argument is the address where the
+ function ends. */
+
+extern boolean debug_end_function PARAMS ((PTR, bfd_vma));
+
+/* Start a block in a function. All local information will be
+ recorded in this block, until the matching call to debug_end_block.
+ debug_start_block and debug_end_block may be nested. The argument
+ is the address at which this block starts. */
+
+extern boolean debug_start_block PARAMS ((PTR, bfd_vma));
+
+/* Finish a block in a function. This matches the call to
+ debug_start_block. The argument is the address at which this block
+ ends. */
+
+extern boolean debug_end_block PARAMS ((PTR, bfd_vma));
+
+/* Associate a line number in the current source file with a given
+ address. */
+
+extern boolean debug_record_line PARAMS ((PTR, unsigned long, bfd_vma));
+
+/* Start a named common block. This is a block of variables that may
+ move in memory. */
+
+extern boolean debug_start_common_block PARAMS ((PTR, const char *));
+
+/* End a named common block. */
+
+extern boolean debug_end_common_block PARAMS ((PTR, const char *));
+
+/* Record a named integer constant. */
+
+extern boolean debug_record_int_const PARAMS ((PTR, const char *, bfd_vma));
+
+/* Record a named floating point constant. */
+
+extern boolean debug_record_float_const PARAMS ((PTR, const char *, double));
+
+/* Record a typed constant with an integral value. */
+
+extern boolean debug_record_typed_const
+ PARAMS ((PTR, const char *, debug_type, bfd_vma));
+
+/* Record a label. */
+
+extern boolean debug_record_label
+ PARAMS ((PTR, const char *, debug_type, bfd_vma));
+
+/* Record a variable. */
+
+extern boolean debug_record_variable
+ PARAMS ((PTR, const char *, debug_type, enum debug_var_kind, bfd_vma));
+
+/* Make an indirect type. The first argument is a pointer to the
+ location where the real type will be placed. The second argument
+ is the type tag, if there is one; this may be NULL; the only
+ purpose of this argument is so that debug_get_type_name can return
+ something useful. This function may be used when a type is
+ referenced before it is defined. */
+
+extern debug_type debug_make_indirect_type
+ PARAMS ((PTR, debug_type *, const char *));
+
+/* Make a void type. */
+
+extern debug_type debug_make_void_type PARAMS ((PTR));
+
+/* Make an integer type of a given size. The boolean argument is true
+ if the integer is unsigned. */
+
+extern debug_type debug_make_int_type PARAMS ((PTR, unsigned int, boolean));
+
+/* Make a floating point type of a given size. FIXME: On some
+ platforms, like an Alpha, you probably need to be able to specify
+ the format. */
+
+extern debug_type debug_make_float_type PARAMS ((PTR, unsigned int));
+
+/* Make a boolean type of a given size. */
+
+extern debug_type debug_make_bool_type PARAMS ((PTR, unsigned int));
+
+/* Make a complex type of a given size. */
+
+extern debug_type debug_make_complex_type PARAMS ((PTR, unsigned int));
+
+/* Make a structure type. The second argument is true for a struct,
+ false for a union. The third argument is the size of the struct.
+ The fourth argument is a NULL terminated array of fields. */
+
+extern debug_type debug_make_struct_type
+ PARAMS ((PTR, boolean, bfd_vma, debug_field *));
+
+/* Make an object type. The first three arguments after the handle
+ are the same as for debug_make_struct_type. The next arguments are
+ a NULL terminated array of base classes, a NULL terminated array of
+ methods, the type of the object holding the virtual function table
+ if it is not this object, and a boolean which is true if this
+ object has its own virtual function table. */
+
+extern debug_type debug_make_object_type
+ PARAMS ((PTR, boolean, bfd_vma, debug_field *, debug_baseclass *,
+ debug_method *, debug_type, boolean));
+
+/* Make an enumeration type. The arguments are a null terminated
+ array of strings, and an array of corresponding values. */
+
+extern debug_type debug_make_enum_type
+ PARAMS ((PTR, const char **, bfd_signed_vma *));
+
+/* Make a pointer to a given type. */
+
+extern debug_type debug_make_pointer_type
+ PARAMS ((PTR, debug_type));
+
+/* Make a function type. The second argument is the return type. The
+ third argument is a NULL terminated array of argument types. The
+ fourth argument is true if the function takes a variable number of
+ arguments. If the third argument is NULL, then the argument types
+ are unknown. */
+
+extern debug_type debug_make_function_type
+ PARAMS ((PTR, debug_type, debug_type *, boolean));
+
+/* Make a reference to a given type. */
+
+extern debug_type debug_make_reference_type PARAMS ((PTR, debug_type));
+
+/* Make a range of a given type from a lower to an upper bound. */
+
+extern debug_type debug_make_range_type
+ PARAMS ((PTR, debug_type, bfd_signed_vma, bfd_signed_vma));
+
+/* Make an array type. The second argument is the type of an element
+ of the array. The third argument is the type of a range of the
+ array. The fourth and fifth argument are the lower and upper
+ bounds, respectively (if the bounds are not known, lower should be
+ 0 and upper should be -1). The sixth argument is true if this
+ array is actually a string, as in C. */
+
+extern debug_type debug_make_array_type
+ PARAMS ((PTR, debug_type, debug_type, bfd_signed_vma, bfd_signed_vma,
+ boolean));
+
+/* Make a set of a given type. For example, a Pascal set type. The
+ boolean argument is true if this set is actually a bitstring, as in
+ CHILL. */
+
+extern debug_type debug_make_set_type PARAMS ((PTR, debug_type, boolean));
+
+/* Make a type for a pointer which is relative to an object. The
+ second argument is the type of the object to which the pointer is
+ relative. The third argument is the type that the pointer points
+ to. */
+
+extern debug_type debug_make_offset_type
+ PARAMS ((PTR, debug_type, debug_type));
+
+/* Make a type for a method function. The second argument is the
+ return type. The third argument is the domain. The fourth
+ argument is a NULL terminated array of argument types. The fifth
+ argument is true if the function takes a variable number of
+ arguments, in which case the array of argument types indicates the
+ types of the first arguments. The domain and the argument array
+ may be NULL, in which case this is a stub method and that
+ information is not available. Stabs debugging uses this, and gets
+ the argument types from the mangled name. */
+
+extern debug_type debug_make_method_type
+ PARAMS ((PTR, debug_type, debug_type, debug_type *, boolean));
+
+/* Make a const qualified version of a given type. */
+
+extern debug_type debug_make_const_type PARAMS ((PTR, debug_type));
+
+/* Make a volatile qualified version of a given type. */
+
+extern debug_type debug_make_volatile_type PARAMS ((PTR, debug_type));
+
+/* Make an undefined tagged type. For example, a struct which has
+ been mentioned, but not defined. */
+
+extern debug_type debug_make_undefined_tagged_type
+ PARAMS ((PTR, const char *, enum debug_type_kind));
+
+/* Make a base class for an object. The second argument is the base
+ class type. The third argument is the bit position of this base
+ class in the object. The fourth argument is whether this is a
+ virtual class. The fifth argument is the visibility of the base
+ class. */
+
+extern debug_baseclass debug_make_baseclass
+ PARAMS ((PTR, debug_type, bfd_vma, boolean, enum debug_visibility));
+
+/* Make a field for a struct. The second argument is the name. The
+ third argument is the type of the field. The fourth argument is
+ the bit position of the field. The fifth argument is the size of
+ the field (it may be zero). The sixth argument is the visibility
+ of the field. */
+
+extern debug_field debug_make_field
+ PARAMS ((PTR, const char *, debug_type, bfd_vma, bfd_vma,
+ enum debug_visibility));
+
+/* Make a static member of an object. The second argument is the
+ name. The third argument is the type of the member. The fourth
+ argument is the physical name of the member (i.e., the name as a
+ global variable). The fifth argument is the visibility of the
+ member. */
+
+extern debug_field debug_make_static_member
+ PARAMS ((PTR, const char *, debug_type, const char *,
+ enum debug_visibility));
+
+/* Make a method. The second argument is the name, and the third
+ argument is a NULL terminated array of method variants. Each
+ method variant is a method with this name but with different
+ argument types. */
+
+extern debug_method debug_make_method
+ PARAMS ((PTR, const char *, debug_method_variant *));
+
+/* Make a method variant. The second argument is the physical name of
+ the function. The third argument is the type of the function,
+ probably constructed by debug_make_method_type. The fourth
+ argument is the visibility. The fifth argument is whether this is
+ a const function. The sixth argument is whether this is a volatile
+ function. The seventh argument is the index in the virtual
+ function table, if any. The eighth argument is the virtual
+ function context. */
+
+extern debug_method_variant debug_make_method_variant
+ PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean,
+ boolean, bfd_vma, debug_type));
+
+/* Make a static method argument. The arguments are the same as for
+ debug_make_method_variant, except that the last two are omitted
+ since a static method can not also be virtual. */
+
+extern debug_method_variant debug_make_static_method_variant
+ PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean,
+ boolean));
+
+/* Name a type. This returns a new type with an attached name. */
+
+extern debug_type debug_name_type PARAMS ((PTR, const char *, debug_type));
+
+/* Give a tag to a type, such as a struct or union. This returns a
+ new type with an attached tag. */
+
+extern debug_type debug_tag_type PARAMS ((PTR, const char *, debug_type));
+
+/* Record the size of a given type. */
+
+extern boolean debug_record_type_size PARAMS ((PTR, debug_type, unsigned int));
+
+/* Find a named type. */
+
+extern debug_type debug_find_named_type PARAMS ((PTR, const char *));
+
+/* Find a tagged type. */
+
+extern debug_type debug_find_tagged_type
+ PARAMS ((PTR, const char *, enum debug_type_kind));
+
+/* Get the kind of a type. */
+
+extern enum debug_type_kind debug_get_type_kind PARAMS ((PTR, debug_type));
+
+/* Get the name of a type. */
+
+extern const char *debug_get_type_name PARAMS ((PTR, debug_type));
+
+/* Get the size of a type. */
+
+extern bfd_vma debug_get_type_size PARAMS ((PTR, debug_type));
+
+/* Get the return type of a function or method type. */
+
+extern debug_type debug_get_return_type PARAMS ((PTR, debug_type));
+
+/* Get the NULL terminated array of parameter types for a function or
+ method type (actually, parameter types are not currently stored for
+ function types). This may be used to determine whether a method
+ type is a stub method or not. The last argument points to a
+ boolean which is set to true if the function takes a variable
+ number of arguments. */
+
+extern const debug_type *debug_get_parameter_types PARAMS ((PTR,
+ debug_type,
+ boolean *));
+
+/* Get the target type of a pointer or reference or const or volatile
+ type. */
+
+extern debug_type debug_get_target_type PARAMS ((PTR, debug_type));
+
+/* Get the NULL terminated array of fields for a struct, union, or
+ class. */
+
+extern const debug_field *debug_get_fields PARAMS ((PTR, debug_type));
+
+/* Get the type of a field. */
+
+extern debug_type debug_get_field_type PARAMS ((PTR, debug_field));
+
+/* Get the name of a field. */
+
+extern const char *debug_get_field_name PARAMS ((PTR, debug_field));
+
+/* Get the bit position of a field within the containing structure.
+ If the field is a static member, this will return (bfd_vma) -1. */
+
+extern bfd_vma debug_get_field_bitpos PARAMS ((PTR, debug_field));
+
+/* Get the bit size of a field. If the field is a static member, this
+ will return (bfd_vma) -1. */
+
+extern bfd_vma debug_get_field_bitsize PARAMS ((PTR, debug_field));
+
+/* Get the visibility of a field. */
+
+extern enum debug_visibility debug_get_field_visibility
+ PARAMS ((PTR, debug_field));
+
+/* Get the physical name of a field, if it is a static member. If the
+ field is not a static member, this will return NULL. */
+
+extern const char *debug_get_field_physname PARAMS ((PTR, debug_field));
+
+/* Write out the recorded debugging information. This takes a set of
+ function pointers which are called to do the actual writing. The
+ first PTR is the debugging handle. The second PTR is a handle
+ which is passed to the functions. */
+
+extern boolean debug_write PARAMS ((PTR, const struct debug_write_fns *, PTR));
+
+#endif /* DEBUG_H */
diff --git a/gnu/usr.bin/binutils/binutils/dep-in.sed b/gnu/usr.bin/binutils/binutils/dep-in.sed
new file mode 100644
index 00000000000..278f2534068
--- /dev/null
+++ b/gnu/usr.bin/binutils/binutils/dep-in.sed
@@ -0,0 +1,16 @@
+:loop
+/\\$/N
+/\\$/b loop
+
+s!@INCDIR@!$(INCDIR)!g
+s!@BFDDIR@!$(BFDDIR)!g
+s!@SRCDIR@/!!g
+
+s/\\\n */ /g
+
+s/ *$//
+s/ */ /g
+/:$/d
+
+s/\(.\{50\}[^ ]*\) /\1 \\\
+ /g
diff --git a/gnu/usr.bin/binutils/binutils/ieee.c b/gnu/usr.bin/binutils/binutils/ieee.c
new file mode 100644
index 00000000000..1ed3315645f
--- /dev/null
+++ b/gnu/usr.bin/binutils/binutils/ieee.c
@@ -0,0 +1,7485 @@
+/* ieee.c -- Read and write IEEE-695 debugging information.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ 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. */
+
+/* This file reads and writes IEEE-695 debugging information. */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "bfd.h"
+#include "ieee.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* This structure holds an entry on the block stack. */
+
+struct ieee_block
+{
+ /* The kind of block. */
+ int kind;
+ /* The source file name, for a BB5 block. */
+ const char *filename;
+ /* The index of the function type, for a BB4 or BB6 block. */
+ unsigned int fnindx;
+ /* True if this function is being skipped. */
+ boolean skip;
+};
+
+/* This structure is the block stack. */
+
+#define BLOCKSTACK_SIZE (16)
+
+struct ieee_blockstack
+{
+ /* The stack pointer. */
+ struct ieee_block *bsp;
+ /* The stack. */
+ struct ieee_block stack[BLOCKSTACK_SIZE];
+};
+
+/* This structure holds information for a variable. */
+
+struct ieee_var
+{
+ /* Start of name. */
+ const char *name;
+ /* Length of name. */
+ unsigned long namlen;
+ /* Type. */
+ debug_type type;
+ /* Slot if we make an indirect type. */
+ debug_type *pslot;
+ /* Kind of variable or function. */
+ enum
+ {
+ IEEE_UNKNOWN,
+ IEEE_EXTERNAL,
+ IEEE_GLOBAL,
+ IEEE_STATIC,
+ IEEE_LOCAL,
+ IEEE_FUNCTION
+ } kind;
+};
+
+/* This structure holds all the variables. */
+
+struct ieee_vars
+{
+ /* Number of slots allocated. */
+ unsigned int alloc;
+ /* Variables. */
+ struct ieee_var *vars;
+};
+
+/* This structure holds information for a type. We need this because
+ we don't want to represent bitfields as real types. */
+
+struct ieee_type
+{
+ /* Type. */
+ debug_type type;
+ /* Slot if this is type is referenced before it is defined. */
+ debug_type *pslot;
+ /* Slots for arguments if we make indirect types for them. */
+ debug_type *arg_slots;
+ /* If this is a bitfield, this is the size in bits. If this is not
+ a bitfield, this is zero. */
+ unsigned long bitsize;
+};
+
+/* This structure holds all the type information. */
+
+struct ieee_types
+{
+ /* Number of slots allocated. */
+ unsigned int alloc;
+ /* Types. */
+ struct ieee_type *types;
+ /* Builtin types. */
+#define BUILTIN_TYPE_COUNT (60)
+ debug_type builtins[BUILTIN_TYPE_COUNT];
+};
+
+/* This structure holds a linked last of structs with their tag names,
+ so that we can convert them to C++ classes if necessary. */
+
+struct ieee_tag
+{
+ /* Next tag. */
+ struct ieee_tag *next;
+ /* This tag name. */
+ const char *name;
+ /* The type of the tag. */
+ debug_type type;
+ /* The tagged type is an indirect type pointing at this slot. */
+ debug_type slot;
+ /* This is an array of slots used when a field type is converted
+ into a indirect type, in case it needs to be later converted into
+ a reference type. */
+ debug_type *fslots;
+};
+
+/* This structure holds the information we pass around to the parsing
+ functions. */
+
+struct ieee_info
+{
+ /* The debugging handle. */
+ PTR dhandle;
+ /* The BFD. */
+ bfd *abfd;
+ /* The start of the bytes to be parsed. */
+ const bfd_byte *bytes;
+ /* The end of the bytes to be parsed. */
+ const bfd_byte *pend;
+ /* The block stack. */
+ struct ieee_blockstack blockstack;
+ /* The variables. */
+ struct ieee_vars vars;
+ /* The global variables, after a global typedef block. */
+ struct ieee_vars *global_vars;
+ /* The types. */
+ struct ieee_types types;
+ /* The list of tagged structs. */
+ struct ieee_tag *tags;
+};
+
+/* Basic builtin types, not including the pointers. */
+
+enum builtin_types
+{
+ builtin_unknown = 0,
+ builtin_void = 1,
+ builtin_signed_char = 2,
+ builtin_unsigned_char = 3,
+ builtin_signed_short_int = 4,
+ builtin_unsigned_short_int = 5,
+ builtin_signed_long = 6,
+ builtin_unsigned_long = 7,
+ builtin_signed_long_long = 8,
+ builtin_unsigned_long_long = 9,
+ builtin_float = 10,
+ builtin_double = 11,
+ builtin_long_double = 12,
+ builtin_long_long_double = 13,
+ builtin_quoted_string = 14,
+ builtin_instruction_address = 15,
+ builtin_int = 16,
+ builtin_unsigned = 17,
+ builtin_unsigned_int = 18,
+ builtin_char = 19,
+ builtin_long = 20,
+ builtin_short = 21,
+ builtin_unsigned_short = 22,
+ builtin_short_int = 23,
+ builtin_signed_short = 24,
+ builtin_bcd_float = 25
+};
+
+/* These are the values found in the derivation flags of a 'b'
+ component record of a 'T' type extension record in a C++ pmisc
+ record. These are bitmasks. */
+
+/* Set for a private base class, clear for a public base class.
+ Protected base classes are not supported. */
+#define BASEFLAGS_PRIVATE (0x1)
+/* Set for a virtual base class. */
+#define BASEFLAGS_VIRTUAL (0x2)
+/* Set for a friend class, clear for a base class. */
+#define BASEFLAGS_FRIEND (0x10)
+
+/* These are the values found in the specs flags of a 'd', 'm', or 'v'
+ component record of a 'T' type extension record in a C++ pmisc
+ record. The same flags are used for a 'M' record in a C++ pmisc
+ record. */
+
+/* The lower two bits hold visibility information. */
+#define CXXFLAGS_VISIBILITY (0x3)
+/* This value in the lower two bits indicates a public member. */
+#define CXXFLAGS_VISIBILITY_PUBLIC (0x0)
+/* This value in the lower two bits indicates a private member. */
+#define CXXFLAGS_VISIBILITY_PRIVATE (0x1)
+/* This value in the lower two bits indicates a protected member. */
+#define CXXFLAGS_VISIBILITY_PROTECTED (0x2)
+/* Set for a static member. */
+#define CXXFLAGS_STATIC (0x4)
+/* Set for a virtual override. */
+#define CXXFLAGS_OVERRIDE (0x8)
+/* Set for a friend function. */
+#define CXXFLAGS_FRIEND (0x10)
+/* Set for a const function. */
+#define CXXFLAGS_CONST (0x20)
+/* Set for a volatile function. */
+#define CXXFLAGS_VOLATILE (0x40)
+/* Set for an overloaded function. */
+#define CXXFLAGS_OVERLOADED (0x80)
+/* Set for an operator function. */
+#define CXXFLAGS_OPERATOR (0x100)
+/* Set for a constructor or destructor. */
+#define CXXFLAGS_CTORDTOR (0x400)
+/* Set for a constructor. */
+#define CXXFLAGS_CTOR (0x200)
+/* Set for an inline function. */
+#define CXXFLAGS_INLINE (0x800)
+
+/* Local functions. */
+
+static void ieee_error
+ PARAMS ((struct ieee_info *, const bfd_byte *, const char *));
+static void ieee_eof PARAMS ((struct ieee_info *));
+static char *savestring PARAMS ((const char *, unsigned long));
+static boolean ieee_read_number
+ PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
+static boolean ieee_read_optional_number
+ PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *, boolean *));
+static boolean ieee_read_id
+ PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
+ unsigned long *));
+static boolean ieee_read_optional_id
+ PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
+ unsigned long *, boolean *));
+static boolean ieee_read_expression
+ PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
+static debug_type ieee_builtin_type
+ PARAMS ((struct ieee_info *, const bfd_byte *, unsigned int));
+static boolean ieee_alloc_type
+ PARAMS ((struct ieee_info *, unsigned int, boolean));
+static boolean ieee_read_type_index
+ PARAMS ((struct ieee_info *, const bfd_byte **, debug_type *));
+static int ieee_regno_to_genreg PARAMS ((bfd *, int));
+static int ieee_genreg_to_regno PARAMS ((bfd *, int));
+static boolean parse_ieee_bb PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_be PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_nn PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_ty PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_atn PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean ieee_read_cxx_misc
+ PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
+static boolean ieee_read_cxx_class
+ PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
+static boolean ieee_read_cxx_defaults
+ PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
+static boolean ieee_read_reference
+ PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean ieee_require_asn
+ PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
+static boolean ieee_require_atn65
+ PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
+ unsigned long *));
+
+/* Report an error in the IEEE debugging information. */
+
+static void
+ieee_error (info, p, s)
+ struct ieee_info *info;
+ const bfd_byte *p;
+ const char *s;
+{
+ if (p != NULL)
+ fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (info->abfd),
+ (unsigned long) (p - info->bytes), s, *p);
+ else
+ fprintf (stderr, "%s: %s\n", bfd_get_filename (info->abfd), s);
+}
+
+/* Report an unexpected EOF in the IEEE debugging information. */
+
+static void
+ieee_eof (info)
+ struct ieee_info *info;
+{
+ ieee_error (info, (const bfd_byte *) NULL,
+ "unexpected end of debugging information");
+}
+
+/* Save a string in memory. */
+
+static char *
+savestring (start, len)
+ const char *start;
+ unsigned long len;
+{
+ char *ret;
+
+ ret = (char *) xmalloc (len + 1);
+ memcpy (ret, start, len);
+ ret[len] = '\0';
+ return ret;
+}
+
+/* Read a number which must be present in an IEEE file. */
+
+static boolean
+ieee_read_number (info, pp, pv)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ bfd_vma *pv;
+{
+ return ieee_read_optional_number (info, pp, pv, (boolean *) NULL);
+}
+
+/* Read a number in an IEEE file. If ppresent is not NULL, the number
+ need not be there. */
+
+static boolean
+ieee_read_optional_number (info, pp, pv, ppresent)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ bfd_vma *pv;
+ boolean *ppresent;
+{
+ ieee_record_enum_type b;
+
+ if (*pp >= info->pend)
+ {
+ if (ppresent != NULL)
+ {
+ *ppresent = false;
+ return true;
+ }
+ ieee_eof (info);
+ return false;
+ }
+
+ b = (ieee_record_enum_type) **pp;
+ ++*pp;
+
+ if (b <= ieee_number_end_enum)
+ {
+ *pv = (bfd_vma) b;
+ if (ppresent != NULL)
+ *ppresent = true;
+ return true;
+ }
+
+ if (b >= ieee_number_repeat_start_enum && b <= ieee_number_repeat_end_enum)
+ {
+ unsigned int i;
+
+ i = (int) b - (int) ieee_number_repeat_start_enum;
+ if (*pp + i - 1 >= info->pend)
+ {
+ ieee_eof (info);
+ return false;
+ }
+
+ *pv = 0;
+ for (; i > 0; i--)
+ {
+ *pv <<= 8;
+ *pv += **pp;
+ ++*pp;
+ }
+
+ if (ppresent != NULL)
+ *ppresent = true;
+
+ return true;
+ }
+
+ if (ppresent != NULL)
+ {
+ --*pp;
+ *ppresent = false;
+ return true;
+ }
+
+ ieee_error (info, *pp - 1, "invalid number");
+ return false;
+}
+
+/* Read a required string from an IEEE file. */
+
+static boolean
+ieee_read_id (info, pp, pname, pnamlen)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ const char **pname;
+ unsigned long *pnamlen;
+{
+ return ieee_read_optional_id (info, pp, pname, pnamlen, (boolean *) NULL);
+}
+
+/* Read a string from an IEEE file. If ppresent is not NULL, the
+ string is optional. */
+
+static boolean
+ieee_read_optional_id (info, pp, pname, pnamlen, ppresent)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ const char **pname;
+ unsigned long *pnamlen;
+ boolean *ppresent;
+{
+ bfd_byte b;
+ unsigned long len;
+
+ if (*pp >= info->pend)
+ {
+ ieee_eof (info);
+ return false;
+ }
+
+ b = **pp;
+ ++*pp;
+
+ if (b <= 0x7f)
+ len = b;
+ else if ((ieee_record_enum_type) b == ieee_extension_length_1_enum)
+ {
+ len = **pp;
+ ++*pp;
+ }
+ else if ((ieee_record_enum_type) b == ieee_extension_length_2_enum)
+ {
+ len = (**pp << 8) + (*pp)[1];
+ *pp += 2;
+ }
+ else
+ {
+ if (ppresent != NULL)
+ {
+ --*pp;
+ *ppresent = false;
+ return true;
+ }
+ ieee_error (info, *pp - 1, "invalid string length");
+ return false;
+ }
+
+ if ((unsigned long) (info->pend - *pp) < len)
+ {
+ ieee_eof (info);
+ return false;
+ }
+
+ *pname = (const char *) *pp;
+ *pnamlen = len;
+ *pp += len;
+
+ if (ppresent != NULL)
+ *ppresent = true;
+
+ return true;
+}
+
+/* Read an expression from an IEEE file. Since this code is only used
+ to parse debugging information, I haven't bothered to write a full
+ blown IEEE expression parser. I've only thrown in the things I've
+ seen in debugging information. This can be easily extended if
+ necessary. */
+
+static boolean
+ieee_read_expression (info, pp, pv)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ bfd_vma *pv;
+{
+ const bfd_byte *expr_start;
+#define EXPR_STACK_SIZE (10)
+ bfd_vma expr_stack[EXPR_STACK_SIZE];
+ bfd_vma *esp;
+
+ expr_start = *pp;
+
+ esp = expr_stack;
+
+ while (1)
+ {
+ const bfd_byte *start;
+ bfd_vma val;
+ boolean present;
+ ieee_record_enum_type c;
+
+ start = *pp;
+
+ if (! ieee_read_optional_number (info, pp, &val, &present))
+ return false;
+
+ if (present)
+ {
+ if (esp - expr_stack >= EXPR_STACK_SIZE)
+ {
+ ieee_error (info, start, "expression stack overflow");
+ return false;
+ }
+ *esp++ = val;
+ continue;
+ }
+
+ c = (ieee_record_enum_type) **pp;
+
+ if (c >= ieee_module_beginning_enum)
+ break;
+
+ ++*pp;
+
+ if (c == ieee_comma)
+ break;
+
+ switch (c)
+ {
+ default:
+ ieee_error (info, start, "unsupported IEEE expression operator");
+ break;
+
+ case ieee_variable_R_enum:
+ {
+ bfd_vma indx;
+ asection *s;
+
+ if (! ieee_read_number (info, pp, &indx))
+ return false;
+ for (s = info->abfd->sections; s != NULL; s = s->next)
+ if ((bfd_vma) s->target_index == indx)
+ break;
+ if (s == NULL)
+ {
+ ieee_error (info, start, "unknown section");
+ return false;
+ }
+
+ if (esp - expr_stack >= EXPR_STACK_SIZE)
+ {
+ ieee_error (info, start, "expression stack overflow");
+ return false;
+ }
+
+ *esp++ = bfd_get_section_vma (info->abfd, s);
+ }
+ break;
+
+ case ieee_function_plus_enum:
+ case ieee_function_minus_enum:
+ {
+ bfd_vma v1, v2;
+
+ if (esp - expr_stack < 2)
+ {
+ ieee_error (info, start, "expression stack underflow");
+ return false;
+ }
+
+ v1 = *--esp;
+ v2 = *--esp;
+ *esp++ = v1 + v2;
+ }
+ break;
+ }
+ }
+
+ if (esp - 1 != expr_stack)
+ {
+ ieee_error (info, expr_start, "expression stack mismatch");
+ return false;
+ }
+
+ *pv = *--esp;
+
+ return true;
+}
+
+/* Return an IEEE builtin type. */
+
+static debug_type
+ieee_builtin_type (info, p, indx)
+ struct ieee_info *info;
+ const bfd_byte *p;
+ unsigned int indx;
+{
+ PTR dhandle;
+ debug_type type;
+ const char *name;
+
+ if (indx < BUILTIN_TYPE_COUNT
+ && info->types.builtins[indx] != DEBUG_TYPE_NULL)
+ return info->types.builtins[indx];
+
+ dhandle = info->dhandle;
+
+ if (indx >= 32 && indx < 64)
+ {
+ type = debug_make_pointer_type (dhandle,
+ ieee_builtin_type (info, p, indx - 32));
+ assert (indx < BUILTIN_TYPE_COUNT);
+ info->types.builtins[indx] = type;
+ return type;
+ }
+
+ switch ((enum builtin_types) indx)
+ {
+ default:
+ ieee_error (info, p, "unknown builtin type");
+ return NULL;
+
+ case builtin_unknown:
+ type = debug_make_void_type (dhandle);
+ name = NULL;
+ break;
+
+ case builtin_void:
+ type = debug_make_void_type (dhandle);
+ name = "void";
+ break;
+
+ case builtin_signed_char:
+ type = debug_make_int_type (dhandle, 1, false);
+ name = "signed char";
+ break;
+
+ case builtin_unsigned_char:
+ type = debug_make_int_type (dhandle, 1, true);
+ name = "unsigned char";
+ break;
+
+ case builtin_signed_short_int:
+ type = debug_make_int_type (dhandle, 2, false);
+ name = "signed short int";
+ break;
+
+ case builtin_unsigned_short_int:
+ type = debug_make_int_type (dhandle, 2, true);
+ name = "unsigned short int";
+ break;
+
+ case builtin_signed_long:
+ type = debug_make_int_type (dhandle, 4, false);
+ name = "signed long";
+ break;
+
+ case builtin_unsigned_long:
+ type = debug_make_int_type (dhandle, 4, true);
+ name = "unsigned long";
+ break;
+
+ case builtin_signed_long_long:
+ type = debug_make_int_type (dhandle, 8, false);
+ name = "signed long long";
+ break;
+
+ case builtin_unsigned_long_long:
+ type = debug_make_int_type (dhandle, 8, true);
+ name = "unsigned long long";
+ break;
+
+ case builtin_float:
+ type = debug_make_float_type (dhandle, 4);
+ name = "float";
+ break;
+
+ case builtin_double:
+ type = debug_make_float_type (dhandle, 8);
+ name = "double";
+ break;
+
+ case builtin_long_double:
+ /* FIXME: The size for this type should depend upon the
+ processor. */
+ type = debug_make_float_type (dhandle, 12);
+ name = "long double";
+ break;
+
+ case builtin_long_long_double:
+ type = debug_make_float_type (dhandle, 16);
+ name = "long long double";
+ break;
+
+ case builtin_quoted_string:
+ type = debug_make_array_type (dhandle,
+ ieee_builtin_type (info, p,
+ ((unsigned int)
+ builtin_char)),
+ ieee_builtin_type (info, p,
+ ((unsigned int)
+ builtin_int)),
+ 0, -1, true);
+ name = "QUOTED STRING";
+ break;
+
+ case builtin_instruction_address:
+ /* FIXME: This should be a code address. */
+ type = debug_make_int_type (dhandle, 4, true);
+ name = "instruction address";
+ break;
+
+ case builtin_int:
+ /* FIXME: The size for this type should depend upon the
+ processor. */
+ type = debug_make_int_type (dhandle, 4, false);
+ name = "int";
+ break;
+
+ case builtin_unsigned:
+ /* FIXME: The size for this type should depend upon the
+ processor. */
+ type = debug_make_int_type (dhandle, 4, true);
+ name = "unsigned";
+ break;
+
+ case builtin_unsigned_int:
+ /* FIXME: The size for this type should depend upon the
+ processor. */
+ type = debug_make_int_type (dhandle, 4, true);
+ name = "unsigned int";
+ break;
+
+ case builtin_char:
+ type = debug_make_int_type (dhandle, 1, false);
+ name = "char";
+ break;
+
+ case builtin_long:
+ type = debug_make_int_type (dhandle, 4, false);
+ name = "long";
+ break;
+
+ case builtin_short:
+ type = debug_make_int_type (dhandle, 2, false);
+ name = "short";
+ break;
+
+ case builtin_unsigned_short:
+ type = debug_make_int_type (dhandle, 2, true);
+ name = "unsigned short";
+ break;
+
+ case builtin_short_int:
+ type = debug_make_int_type (dhandle, 2, false);
+ name = "short int";
+ break;
+
+ case builtin_signed_short:
+ type = debug_make_int_type (dhandle, 2, false);
+ name = "signed short";
+ break;
+
+ case builtin_bcd_float:
+ ieee_error (info, p, "BCD float type not supported");
+ return false;
+ }
+
+ if (name != NULL)
+ type = debug_name_type (dhandle, name, type);
+
+ assert (indx < BUILTIN_TYPE_COUNT);
+
+ info->types.builtins[indx] = type;
+
+ return type;
+}
+
+/* Allocate more space in the type table. If ref is true, this is a
+ reference to the type; if it is not already defined, we should set
+ up an indirect type. */
+
+static boolean
+ieee_alloc_type (info, indx, ref)
+ struct ieee_info *info;
+ unsigned int indx;
+ boolean ref;
+{
+ unsigned int nalloc;
+ register struct ieee_type *t;
+ struct ieee_type *tend;
+
+ if (indx >= info->types.alloc)
+ {
+ nalloc = info->types.alloc;
+ if (nalloc == 0)
+ nalloc = 4;
+ while (indx >= nalloc)
+ nalloc *= 2;
+
+ info->types.types = ((struct ieee_type *)
+ xrealloc (info->types.types,
+ nalloc * sizeof *info->types.types));
+
+ memset (info->types.types + info->types.alloc, 0,
+ (nalloc - info->types.alloc) * sizeof *info->types.types);
+
+ tend = info->types.types + nalloc;
+ for (t = info->types.types + info->types.alloc; t < tend; t++)
+ t->type = DEBUG_TYPE_NULL;
+
+ info->types.alloc = nalloc;
+ }
+
+ if (ref)
+ {
+ t = info->types.types + indx;
+ if (t->type == NULL)
+ {
+ t->pslot = (debug_type *) xmalloc (sizeof *t->pslot);
+ *t->pslot = DEBUG_TYPE_NULL;
+ t->type = debug_make_indirect_type (info->dhandle, t->pslot,
+ (const char *) NULL);
+ if (t->type == NULL)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Read a type index and return the corresponding type. */
+
+static boolean
+ieee_read_type_index (info, pp, ptype)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ debug_type *ptype;
+{
+ const bfd_byte *start;
+ bfd_vma indx;
+
+ start = *pp;
+
+ if (! ieee_read_number (info, pp, &indx))
+ return false;
+
+ if (indx < 256)
+ {
+ *ptype = ieee_builtin_type (info, start, indx);
+ if (*ptype == NULL)
+ return false;
+ return true;
+ }
+
+ indx -= 256;
+ if (! ieee_alloc_type (info, indx, true))
+ return false;
+
+ *ptype = info->types.types[indx].type;
+
+ return true;
+}
+
+/* Parse IEEE debugging information for a file. This is passed the
+ bytes which compose the Debug Information Part of an IEEE file. */
+
+boolean
+parse_ieee (dhandle, abfd, bytes, len)
+ PTR dhandle;
+ bfd *abfd;
+ const bfd_byte *bytes;
+ bfd_size_type len;
+{
+ struct ieee_info info;
+ unsigned int i;
+ const bfd_byte *p, *pend;
+
+ info.dhandle = dhandle;
+ info.abfd = abfd;
+ info.bytes = bytes;
+ info.pend = bytes + len;
+ info.blockstack.bsp = info.blockstack.stack;
+ info.vars.alloc = 0;
+ info.vars.vars = NULL;
+ info.types.alloc = 0;
+ info.types.types = NULL;
+ info.tags = NULL;
+ for (i = 0; i < BUILTIN_TYPE_COUNT; i++)
+ info.types.builtins[i] = DEBUG_TYPE_NULL;
+
+ p = bytes;
+ pend = info.pend;
+ while (p < pend)
+ {
+ const bfd_byte *record_start;
+ ieee_record_enum_type c;
+
+ record_start = p;
+
+ c = (ieee_record_enum_type) *p++;
+
+ if (c == ieee_at_record_enum)
+ c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++);
+
+ if (c <= ieee_number_repeat_end_enum)
+ {
+ ieee_error (&info, record_start, "unexpected number");
+ return false;
+ }
+
+ switch (c)
+ {
+ default:
+ ieee_error (&info, record_start, "unexpected record type");
+ return false;
+
+ case ieee_bb_record_enum:
+ if (! parse_ieee_bb (&info, &p))
+ return false;
+ break;
+
+ case ieee_be_record_enum:
+ if (! parse_ieee_be (&info, &p))
+ return false;
+ break;
+
+ case ieee_nn_record:
+ if (! parse_ieee_nn (&info, &p))
+ return false;
+ break;
+
+ case ieee_ty_record_enum:
+ if (! parse_ieee_ty (&info, &p))
+ return false;
+ break;
+
+ case ieee_atn_record_enum:
+ if (! parse_ieee_atn (&info, &p))
+ return false;
+ break;
+ }
+ }
+
+ if (info.blockstack.bsp != info.blockstack.stack)
+ {
+ ieee_error (&info, (const bfd_byte *) NULL,
+ "blocks left on stack at end");
+ return false;
+ }
+
+ return true;
+}
+
+/* Handle an IEEE BB record. */
+
+static boolean
+parse_ieee_bb (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ const bfd_byte *block_start;
+ bfd_byte b;
+ bfd_vma size;
+ const char *name;
+ unsigned long namlen;
+ char *namcopy;
+ unsigned int fnindx;
+ boolean skip;
+
+ block_start = *pp;
+
+ b = **pp;
+ ++*pp;
+
+ if (! ieee_read_number (info, pp, &size)
+ || ! ieee_read_id (info, pp, &name, &namlen))
+ return false;
+
+ fnindx = (unsigned int) -1;
+ skip = false;
+
+ switch (b)
+ {
+ case 1:
+ /* BB1: Type definitions local to a module. */
+ namcopy = savestring (name, namlen);
+ if (namcopy == NULL)
+ return false;
+ if (! debug_set_filename (info->dhandle, namcopy))
+ return false;
+ break;
+
+ case 2:
+ /* BB2: Global type definitions. The name is supposed to be
+ empty, but we don't check. */
+ if (! debug_set_filename (info->dhandle, "*global*"))
+ return false;
+ break;
+
+ case 3:
+ /* BB3: High level module block begin. We don't have to do
+ anything here. The name is supposed to be the same as for
+ the BB1, but we don't check. */
+ break;
+
+ case 4:
+ /* BB4: Global function. */
+ {
+ bfd_vma stackspace, typindx, offset;
+ debug_type return_type;
+
+ if (! ieee_read_number (info, pp, &stackspace)
+ || ! ieee_read_number (info, pp, &typindx)
+ || ! ieee_read_expression (info, pp, &offset))
+ return false;
+
+ /* We have no way to record the stack space. FIXME. */
+
+ if (typindx < 256)
+ {
+ return_type = ieee_builtin_type (info, block_start, typindx);
+ if (return_type == DEBUG_TYPE_NULL)
+ return false;
+ }
+ else
+ {
+ typindx -= 256;
+ if (! ieee_alloc_type (info, typindx, true))
+ return false;
+ fnindx = typindx;
+ return_type = info->types.types[typindx].type;
+ if (debug_get_type_kind (info->dhandle, return_type)
+ == DEBUG_KIND_FUNCTION)
+ return_type = debug_get_return_type (info->dhandle,
+ return_type);
+ }
+
+ namcopy = savestring (name, namlen);
+ if (namcopy == NULL)
+ return false;
+ if (! debug_record_function (info->dhandle, namcopy, return_type,
+ true, offset))
+ return false;
+ }
+ break;
+
+ case 5:
+ /* BB5: File name for source line numbers. */
+ {
+ unsigned int i;
+
+ /* We ignore the date and time. FIXME. */
+ for (i = 0; i < 6; i++)
+ {
+ bfd_vma ignore;
+ boolean present;
+
+ if (! ieee_read_optional_number (info, pp, &ignore, &present))
+ return false;
+ if (! present)
+ break;
+ }
+
+ namcopy = savestring (name, namlen);
+ if (namcopy == NULL)
+ return false;
+ if (! debug_start_source (info->dhandle, namcopy))
+ return false;
+ }
+ break;
+
+ case 6:
+ /* BB6: Local function or block. */
+ {
+ bfd_vma stackspace, typindx, offset;
+
+ if (! ieee_read_number (info, pp, &stackspace)
+ || ! ieee_read_number (info, pp, &typindx)
+ || ! ieee_read_expression (info, pp, &offset))
+ return false;
+
+ /* We have no way to record the stack space. FIXME. */
+
+ if (namlen == 0)
+ {
+ if (! debug_start_block (info->dhandle, offset))
+ return false;
+ /* Change b to indicate that this is a block
+ rather than a function. */
+ b = 0x86;
+ }
+ else
+ {
+ /* The MRI C++ compiler will output a fake function named
+ __XRYCPP to hold C++ debugging information. We skip
+ that function. This is not crucial, but it makes
+ converting from IEEE to other debug formats work
+ better. */
+ if (strncmp (name, "__XRYCPP", namlen) == 0)
+ skip = true;
+ else
+ {
+ debug_type return_type;
+
+ if (typindx < 256)
+ {
+ return_type = ieee_builtin_type (info, block_start,
+ typindx);
+ if (return_type == NULL)
+ return false;
+ }
+ else
+ {
+ typindx -= 256;
+ if (! ieee_alloc_type (info, typindx, true))
+ return false;
+ fnindx = typindx;
+ return_type = info->types.types[typindx].type;
+ if (debug_get_type_kind (info->dhandle, return_type)
+ == DEBUG_KIND_FUNCTION)
+ return_type = debug_get_return_type (info->dhandle,
+ return_type);
+ }
+
+ namcopy = savestring (name, namlen);
+ if (namcopy == NULL)
+ return false;
+ if (! debug_record_function (info->dhandle, namcopy,
+ return_type, false, offset))
+ return false;
+ }
+ }
+ }
+ break;
+
+ case 10:
+ /* BB10: Assembler module scope. We completely ignore all this
+ information. FIXME. */
+ {
+ const char *inam, *vstr;
+ unsigned long inamlen, vstrlen;
+ bfd_vma tool_type;
+ boolean present;
+ unsigned int i;
+
+ if (! ieee_read_id (info, pp, &inam, &inamlen)
+ || ! ieee_read_number (info, pp, &tool_type)
+ || ! ieee_read_optional_id (info, pp, &vstr, &vstrlen, &present))
+ return false;
+ for (i = 0; i < 6; i++)
+ {
+ bfd_vma ignore;
+
+ if (! ieee_read_optional_number (info, pp, &ignore, &present))
+ return false;
+ if (! present)
+ break;
+ }
+ }
+ break;
+
+ case 11:
+ /* BB11: Module section. We completely ignore all this
+ information. FIXME. */
+ {
+ bfd_vma sectype, secindx, offset, map;
+ boolean present;
+
+ if (! ieee_read_number (info, pp, &sectype)
+ || ! ieee_read_number (info, pp, &secindx)
+ || ! ieee_read_expression (info, pp, &offset)
+ || ! ieee_read_optional_number (info, pp, &map, &present))
+ return false;
+ }
+ break;
+
+ default:
+ ieee_error (info, block_start, "unknown BB type");
+ return false;
+ }
+
+
+ /* Push this block on the block stack. */
+
+ if (info->blockstack.bsp >= info->blockstack.stack + BLOCKSTACK_SIZE)
+ {
+ ieee_error (info, (const bfd_byte *) NULL, "stack overflow");
+ return false;
+ }
+
+ info->blockstack.bsp->kind = b;
+ if (b == 5)
+ info->blockstack.bsp->filename = namcopy;
+ info->blockstack.bsp->fnindx = fnindx;
+ info->blockstack.bsp->skip = skip;
+ ++info->blockstack.bsp;
+
+ return true;
+}
+
+/* Handle an IEEE BE record. */
+
+static boolean
+parse_ieee_be (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ bfd_vma offset;
+
+ if (info->blockstack.bsp <= info->blockstack.stack)
+ {
+ ieee_error (info, *pp, "stack underflow");
+ return false;
+ }
+ --info->blockstack.bsp;
+
+ switch (info->blockstack.bsp->kind)
+ {
+ case 2:
+ /* When we end the global typedefs block, we copy out the the
+ contents of info->vars. This is because the variable indices
+ may be reused in the local blocks. However, we need to
+ preserve them so that we can locate a function returning a
+ reference variable whose type is named in the global typedef
+ block. */
+ info->global_vars = ((struct ieee_vars *)
+ xmalloc (sizeof *info->global_vars));
+ info->global_vars->alloc = info->vars.alloc;
+ info->global_vars->vars = ((struct ieee_var *)
+ xmalloc (info->vars.alloc
+ * sizeof (*info->vars.vars)));
+ memcpy (info->global_vars->vars, info->vars.vars,
+ info->vars.alloc * sizeof (*info->vars.vars));
+ break;
+
+ case 4:
+ case 6:
+ if (! ieee_read_expression (info, pp, &offset))
+ return false;
+ if (! info->blockstack.bsp->skip)
+ {
+ if (! debug_end_function (info->dhandle, offset + 1))
+ return false;
+ }
+ break;
+
+ case 0x86:
+ /* This is BE6 when BB6 started a block rather than a local
+ function. */
+ if (! ieee_read_expression (info, pp, &offset))
+ return false;
+ if (! debug_end_block (info->dhandle, offset + 1))
+ return false;
+ break;
+
+ case 5:
+ /* When we end a BB5, we look up the stack for the last BB5, if
+ there is one, so that we can call debug_start_source. */
+ if (info->blockstack.bsp > info->blockstack.stack)
+ {
+ struct ieee_block *bl;
+
+ bl = info->blockstack.bsp;
+ do
+ {
+ --bl;
+ if (bl->kind == 5)
+ {
+ if (! debug_start_source (info->dhandle, bl->filename))
+ return false;
+ break;
+ }
+ }
+ while (bl != info->blockstack.stack);
+ }
+ break;
+
+ case 11:
+ if (! ieee_read_expression (info, pp, &offset))
+ return false;
+ /* We just ignore the module size. FIXME. */
+ break;
+
+ default:
+ /* Other block types do not have any trailing information. */
+ break;
+ }
+
+ return true;
+}
+
+/* Parse an NN record. */
+
+static boolean
+parse_ieee_nn (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ const bfd_byte *nn_start;
+ bfd_vma varindx;
+ const char *name;
+ unsigned long namlen;
+
+ nn_start = *pp;
+
+ if (! ieee_read_number (info, pp, &varindx)
+ || ! ieee_read_id (info, pp, &name, &namlen))
+ return false;
+
+ if (varindx < 32)
+ {
+ ieee_error (info, nn_start, "illegal variable index");
+ return false;
+ }
+ varindx -= 32;
+
+ if (varindx >= info->vars.alloc)
+ {
+ unsigned int alloc;
+
+ alloc = info->vars.alloc;
+ if (alloc == 0)
+ alloc = 4;
+ while (varindx >= alloc)
+ alloc *= 2;
+ info->vars.vars = ((struct ieee_var *)
+ xrealloc (info->vars.vars,
+ alloc * sizeof *info->vars.vars));
+ memset (info->vars.vars + info->vars.alloc, 0,
+ (alloc - info->vars.alloc) * sizeof *info->vars.vars);
+ info->vars.alloc = alloc;
+ }
+
+ info->vars.vars[varindx].name = name;
+ info->vars.vars[varindx].namlen = namlen;
+
+ return true;
+}
+
+/* Parse a TY record. */
+
+static boolean
+parse_ieee_ty (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ const bfd_byte *ty_start, *ty_var_start, *ty_code_start;
+ bfd_vma typeindx, varindx, tc;
+ PTR dhandle;
+ boolean tag, typdef;
+ debug_type *arg_slots;
+ unsigned long type_bitsize;
+ debug_type type;
+
+ ty_start = *pp;
+
+ if (! ieee_read_number (info, pp, &typeindx))
+ return false;
+
+ if (typeindx < 256)
+ {
+ ieee_error (info, ty_start, "illegal type index");
+ return false;
+ }
+
+ typeindx -= 256;
+ if (! ieee_alloc_type (info, typeindx, false))
+ return false;
+
+ if (**pp != 0xce)
+ {
+ ieee_error (info, *pp, "unknown TY code");
+ return false;
+ }
+ ++*pp;
+
+ ty_var_start = *pp;
+
+ if (! ieee_read_number (info, pp, &varindx))
+ return false;
+
+ if (varindx < 32)
+ {
+ ieee_error (info, ty_var_start, "illegal variable index");
+ return false;
+ }
+ varindx -= 32;
+
+ if (varindx >= info->vars.alloc || info->vars.vars[varindx].name == NULL)
+ {
+ ieee_error (info, ty_var_start, "undefined variable in TY");
+ return false;
+ }
+
+ ty_code_start = *pp;
+
+ if (! ieee_read_number (info, pp, &tc))
+ return false;
+
+ dhandle = info->dhandle;
+
+ tag = false;
+ typdef = false;
+ arg_slots = NULL;
+ type_bitsize = 0;
+ switch (tc)
+ {
+ default:
+ ieee_error (info, ty_code_start, "unknown TY code");
+ return false;
+
+ case '!':
+ /* Unknown type, with size. We treat it as int. FIXME. */
+ {
+ bfd_vma size;
+
+ if (! ieee_read_number (info, pp, &size))
+ return false;
+ type = debug_make_int_type (dhandle, size, false);
+ }
+ break;
+
+ case 'A': /* Array. */
+ case 'a': /* FORTRAN array in column/row order. FIXME: Not
+ distinguished from normal array. */
+ {
+ debug_type ele_type;
+ bfd_vma lower, upper;
+
+ if (! ieee_read_type_index (info, pp, &ele_type)
+ || ! ieee_read_number (info, pp, &lower)
+ || ! ieee_read_number (info, pp, &upper))
+ return false;
+ type = debug_make_array_type (dhandle, ele_type,
+ ieee_builtin_type (info, ty_code_start,
+ ((unsigned int)
+ builtin_int)),
+ (bfd_signed_vma) lower,
+ (bfd_signed_vma) upper,
+ false);
+ }
+ break;
+
+ case 'E':
+ /* Simple enumeration. */
+ {
+ bfd_vma size;
+ unsigned int alloc;
+ const char **names;
+ unsigned int c;
+ bfd_signed_vma *vals;
+ unsigned int i;
+
+ if (! ieee_read_number (info, pp, &size))
+ return false;
+ /* FIXME: we ignore the enumeration size. */
+
+ alloc = 10;
+ names = (const char **) xmalloc (alloc * sizeof *names);
+ memset (names, 0, alloc * sizeof *names);
+ c = 0;
+ while (1)
+ {
+ const char *name;
+ unsigned long namlen;
+ boolean present;
+
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ if (! present)
+ break;
+
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ names = ((const char **)
+ xrealloc (names, alloc * sizeof *names));
+ }
+
+ names[c] = savestring (name, namlen);
+ if (names[c] == NULL)
+ return false;
+ ++c;
+ }
+
+ names[c] = NULL;
+
+ vals = (bfd_signed_vma *) xmalloc (c * sizeof *vals);
+ for (i = 0; i < c; i++)
+ vals[i] = i;
+
+ type = debug_make_enum_type (dhandle, names, vals);
+ tag = true;
+ }
+ break;
+
+ case 'G':
+ /* Struct with bit fields. */
+ {
+ bfd_vma size;
+ unsigned int alloc;
+ debug_field *fields;
+ unsigned int c;
+
+ if (! ieee_read_number (info, pp, &size))
+ return false;
+
+ alloc = 10;
+ fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+ c = 0;
+ while (1)
+ {
+ const char *name;
+ unsigned long namlen;
+ boolean present;
+ debug_type ftype;
+ bfd_vma bitpos, bitsize;
+
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ if (! present)
+ break;
+ if (! ieee_read_type_index (info, pp, &ftype)
+ || ! ieee_read_number (info, pp, &bitpos)
+ || ! ieee_read_number (info, pp, &bitsize))
+ return false;
+
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ fields = ((debug_field *)
+ xrealloc (fields, alloc * sizeof *fields));
+ }
+
+ fields[c] = debug_make_field (dhandle, savestring (name, namlen),
+ ftype, bitpos, bitsize,
+ DEBUG_VISIBILITY_PUBLIC);
+ if (fields[c] == NULL)
+ return false;
+ ++c;
+ }
+
+ fields[c] = NULL;
+
+ type = debug_make_struct_type (dhandle, true, size, fields);
+ tag = true;
+ }
+ break;
+
+ case 'N':
+ /* Enumeration. */
+ {
+ unsigned int alloc;
+ const char **names;
+ bfd_signed_vma *vals;
+ unsigned int c;
+
+ alloc = 10;
+ names = (const char **) xmalloc (alloc * sizeof *names);
+ vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *names);
+ c = 0;
+ while (1)
+ {
+ const char *name;
+ unsigned long namlen;
+ boolean present;
+ bfd_vma val;
+
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ if (! present)
+ break;
+ if (! ieee_read_number (info, pp, &val))
+ return false;
+
+ /* If the length of the name is zero, then the value is
+ actually the size of the enum. We ignore this
+ information. FIXME. */
+ if (namlen == 0)
+ continue;
+
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ names = ((const char **)
+ xrealloc (names, alloc * sizeof *names));
+ vals = ((bfd_signed_vma *)
+ xrealloc (vals, alloc * sizeof *vals));
+ }
+
+ names[c] = savestring (name, namlen);
+ if (names[c] == NULL)
+ return false;
+ vals[c] = (bfd_signed_vma) val;
+ ++c;
+ }
+
+ names[c] = NULL;
+
+ type = debug_make_enum_type (dhandle, names, vals);
+ tag = true;
+ }
+ break;
+
+ case 'O': /* Small pointer. We don't distinguish small and large
+ pointers. FIXME. */
+ case 'P': /* Large pointer. */
+ {
+ debug_type t;
+
+ if (! ieee_read_type_index (info, pp, &t))
+ return false;
+ type = debug_make_pointer_type (dhandle, t);
+ }
+ break;
+
+ case 'R':
+ /* Range. */
+ {
+ bfd_vma low, high, signedp, size;
+
+ if (! ieee_read_number (info, pp, &low)
+ || ! ieee_read_number (info, pp, &high)
+ || ! ieee_read_number (info, pp, &signedp)
+ || ! ieee_read_number (info, pp, &size))
+ return false;
+
+ type = debug_make_range_type (dhandle,
+ debug_make_int_type (dhandle, size,
+ ! signedp),
+ (bfd_signed_vma) low,
+ (bfd_signed_vma) high);
+ }
+ break;
+
+ case 'S': /* Struct. */
+ case 'U': /* Union. */
+ {
+ bfd_vma size;
+ unsigned int alloc;
+ debug_field *fields;
+ unsigned int c;
+
+ if (! ieee_read_number (info, pp, &size))
+ return false;
+
+ alloc = 10;
+ fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+ c = 0;
+ while (1)
+ {
+ const char *name;
+ unsigned long namlen;
+ boolean present;
+ bfd_vma tindx;
+ bfd_vma offset;
+ debug_type ftype;
+ bfd_vma bitsize;
+
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ if (! present)
+ break;
+ if (! ieee_read_number (info, pp, &tindx)
+ || ! ieee_read_number (info, pp, &offset))
+ return false;
+
+ if (tindx < 256)
+ {
+ ftype = ieee_builtin_type (info, ty_code_start, tindx);
+ bitsize = 0;
+ offset *= 8;
+ }
+ else
+ {
+ struct ieee_type *t;
+
+ tindx -= 256;
+ if (! ieee_alloc_type (info, tindx, true))
+ return false;
+ t = info->types.types + tindx;
+ ftype = t->type;
+ bitsize = t->bitsize;
+ if (bitsize == 0)
+ offset *= 8;
+ }
+
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ fields = ((debug_field *)
+ xrealloc (fields, alloc * sizeof *fields));
+ }
+
+ fields[c] = debug_make_field (dhandle, savestring (name, namlen),
+ ftype, offset, bitsize,
+ DEBUG_VISIBILITY_PUBLIC);
+ if (fields[c] == NULL)
+ return false;
+ ++c;
+ }
+
+ fields[c] = NULL;
+
+ type = debug_make_struct_type (dhandle, tc == 'S', size, fields);
+ tag = true;
+ }
+ break;
+
+ case 'T':
+ /* Typedef. */
+ if (! ieee_read_type_index (info, pp, &type))
+ return false;
+ typdef = true;
+ break;
+
+ case 'X':
+ /* Procedure. FIXME: This is an extern declaration, which we
+ have no way of representing. */
+ {
+ bfd_vma attr;
+ debug_type rtype;
+ bfd_vma nargs;
+ boolean present;
+ struct ieee_var *pv;
+
+ /* FIXME: We ignore the attribute and the argument names. */
+
+ if (! ieee_read_number (info, pp, &attr)
+ || ! ieee_read_type_index (info, pp, &rtype)
+ || ! ieee_read_number (info, pp, &nargs))
+ return false;
+ do
+ {
+ const char *name;
+ unsigned long namlen;
+
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ }
+ while (present);
+
+ pv = info->vars.vars + varindx;
+ pv->kind = IEEE_EXTERNAL;
+ if (pv->namlen > 0
+ && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
+ {
+ /* Set up the return type as an indirect type pointing to
+ the variable slot, so that we can change it to a
+ reference later if appropriate. */
+ pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
+ *pv->pslot = rtype;
+ rtype = debug_make_indirect_type (dhandle, pv->pslot,
+ (const char *) NULL);
+ }
+
+ type = debug_make_function_type (dhandle, rtype, (debug_type *) NULL,
+ false);
+ }
+ break;
+
+ case 'V':
+ /* Void. This is not documented, but the MRI compiler emits it. */
+ type = debug_make_void_type (dhandle);
+ break;
+
+ case 'Z':
+ /* Array with 0 lower bound. */
+ {
+ debug_type etype;
+ bfd_vma high;
+
+ if (! ieee_read_type_index (info, pp, &etype)
+ || ! ieee_read_number (info, pp, &high))
+ return false;
+
+ type = debug_make_array_type (dhandle, etype,
+ ieee_builtin_type (info, ty_code_start,
+ ((unsigned int)
+ builtin_int)),
+ 0, (bfd_signed_vma) high, false);
+ }
+ break;
+
+ case 'c': /* Complex. */
+ case 'd': /* Double complex. */
+ {
+ const char *name;
+ unsigned long namlen;
+
+ /* FIXME: I don't know what the name means. */
+
+ if (! ieee_read_id (info, pp, &name, &namlen))
+ return false;
+
+ type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8);
+ }
+ break;
+
+ case 'f':
+ /* Pascal file name. FIXME. */
+ ieee_error (info, ty_code_start, "Pascal file name not supported");
+ return false;
+
+ case 'g':
+ /* Bitfield type. */
+ {
+ bfd_vma signedp, bitsize;
+
+ if (! ieee_read_number (info, pp, &signedp)
+ || ! ieee_read_number (info, pp, &bitsize)
+ || ! ieee_read_type_index (info, pp, &type))
+ return false;
+
+ /* FIXME: This is just a guess. */
+ if (! signedp)
+ type = debug_make_int_type (dhandle, 4, true);
+ type_bitsize = bitsize;
+ }
+ break;
+
+ case 'n':
+ /* Qualifier. */
+ {
+ bfd_vma kind;
+ debug_type t;
+
+ if (! ieee_read_number (info, pp, &kind)
+ || ! ieee_read_type_index (info, pp, &t))
+ return false;
+
+ switch (kind)
+ {
+ default:
+ ieee_error (info, ty_start, "unsupported qualifer");
+ return false;
+
+ case 1:
+ type = debug_make_const_type (dhandle, t);
+ break;
+
+ case 2:
+ type = debug_make_volatile_type (dhandle, t);
+ break;
+ }
+ }
+ break;
+
+ case 's':
+ /* Set. */
+ {
+ bfd_vma size;
+ debug_type etype;
+
+ if (! ieee_read_number (info, pp, &size)
+ || ! ieee_read_type_index (info, pp, &etype))
+ return false;
+
+ /* FIXME: We ignore the size. */
+
+ type = debug_make_set_type (dhandle, etype, false);
+ }
+ break;
+
+ case 'x':
+ /* Procedure with compiler dependencies. */
+ {
+ struct ieee_var *pv;
+ bfd_vma attr, frame_type, push_mask, nargs, level, father;
+ debug_type rtype;
+ debug_type *arg_types;
+ boolean varargs;
+ boolean present;
+
+ /* FIXME: We ignore some of this information. */
+
+ pv = info->vars.vars + varindx;
+
+ if (! ieee_read_number (info, pp, &attr)
+ || ! ieee_read_number (info, pp, &frame_type)
+ || ! ieee_read_number (info, pp, &push_mask)
+ || ! ieee_read_type_index (info, pp, &rtype)
+ || ! ieee_read_number (info, pp, &nargs))
+ return false;
+ if (nargs == (bfd_vma) -1)
+ {
+ arg_types = NULL;
+ varargs = false;
+ }
+ else
+ {
+ unsigned int i;
+
+ arg_types = ((debug_type *)
+ xmalloc ((nargs + 1) * sizeof *arg_types));
+ for (i = 0; i < nargs; i++)
+ if (! ieee_read_type_index (info, pp, arg_types + i))
+ return false;
+
+ /* If the last type is pointer to void, this is really a
+ varargs function. */
+ varargs = false;
+ if (nargs > 0)
+ {
+ debug_type last;
+
+ last = arg_types[nargs - 1];
+ if (debug_get_type_kind (dhandle, last) == DEBUG_KIND_POINTER
+ && (debug_get_type_kind (dhandle,
+ debug_get_target_type (dhandle,
+ last))
+ == DEBUG_KIND_VOID))
+ {
+ --nargs;
+ varargs = true;
+ }
+ }
+
+ /* If there are any pointer arguments, turn them into
+ indirect types in case we later need to convert them to
+ reference types. */
+ for (i = 0; i < nargs; i++)
+ {
+ if (debug_get_type_kind (dhandle, arg_types[i])
+ == DEBUG_KIND_POINTER)
+ {
+ if (arg_slots == NULL)
+ {
+ arg_slots = ((debug_type *)
+ xmalloc (nargs * sizeof *arg_slots));
+ memset (arg_slots, 0, nargs * sizeof *arg_slots);
+ }
+ arg_slots[i] = arg_types[i];
+ arg_types[i] =
+ debug_make_indirect_type (dhandle,
+ arg_slots + i,
+ (const char *) NULL);
+ }
+ }
+
+ arg_types[nargs] = DEBUG_TYPE_NULL;
+ }
+ if (! ieee_read_number (info, pp, &level)
+ || ! ieee_read_optional_number (info, pp, &father, &present))
+ return false;
+
+ /* We can't distinguish between a global function and a static
+ function. */
+ pv->kind = IEEE_FUNCTION;
+
+ if (pv->namlen > 0
+ && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
+ {
+ /* Set up the return type as an indirect type pointing to
+ the variable slot, so that we can change it to a
+ reference later if appropriate. */
+ pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
+ *pv->pslot = rtype;
+ rtype = debug_make_indirect_type (dhandle, pv->pslot,
+ (const char *) NULL);
+ }
+
+ type = debug_make_function_type (dhandle, rtype, arg_types, varargs);
+ }
+ break;
+ }
+
+ /* Record the type in the table. */
+
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ info->vars.vars[varindx].type = type;
+
+ if ((tag || typdef)
+ && info->vars.vars[varindx].namlen > 0)
+ {
+ const char *name;
+
+ name = savestring (info->vars.vars[varindx].name,
+ info->vars.vars[varindx].namlen);
+ if (typdef)
+ type = debug_name_type (dhandle, name, type);
+ else if (tc == 'E' || tc == 'N')
+ type = debug_tag_type (dhandle, name, type);
+ else
+ {
+ struct ieee_tag *it;
+
+ /* We must allocate all struct tags as indirect types, so
+ that if we later see a definition of the tag as a C++
+ record we can update the indirect slot and automatically
+ change all the existing references. */
+ it = (struct ieee_tag *) xmalloc (sizeof *it);
+ memset (it, 0, sizeof *it);
+ it->next = info->tags;
+ info->tags = it;
+ it->name = name;
+ it->slot = type;
+
+ type = debug_make_indirect_type (dhandle, &it->slot, name);
+ type = debug_tag_type (dhandle, name, type);
+
+ it->type = type;
+ }
+ if (type == NULL)
+ return false;
+ }
+
+ info->types.types[typeindx].type = type;
+ info->types.types[typeindx].arg_slots = arg_slots;
+ info->types.types[typeindx].bitsize = type_bitsize;
+
+ /* We may have already allocated type as an indirect type pointing
+ to slot. It does no harm to replace the indirect type with the
+ real type. Filling in slot as well handles the indirect types
+ which are already hanging around. */
+ if (info->types.types[typeindx].pslot != NULL)
+ *info->types.types[typeindx].pslot = type;
+
+ return true;
+}
+
+/* Parse an ATN record. */
+
+static boolean
+parse_ieee_atn (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ const bfd_byte *atn_start, *atn_code_start;
+ bfd_vma varindx;
+ struct ieee_var *pvar;
+ debug_type type;
+ bfd_vma atn_code;
+ PTR dhandle;
+ bfd_vma v, v2, v3, v4, v5;
+ const char *name;
+ unsigned long namlen;
+ char *namcopy;
+ boolean present;
+ int blocktype;
+
+ atn_start = *pp;
+
+ if (! ieee_read_number (info, pp, &varindx)
+ || ! ieee_read_type_index (info, pp, &type))
+ return false;
+
+ atn_code_start = *pp;
+
+ if (! ieee_read_number (info, pp, &atn_code))
+ return false;
+
+ if (varindx == 0)
+ {
+ pvar = NULL;
+ name = "";
+ namlen = 0;
+ }
+ else if (varindx < 32)
+ {
+ ieee_error (info, atn_start, "illegal variable index");
+ return false;
+ }
+ else
+ {
+ varindx -= 32;
+ if (varindx >= info->vars.alloc
+ || info->vars.vars[varindx].name == NULL)
+ {
+ /* The MRI compiler or linker sometimes omits the NN record
+ for a pmisc record. */
+ if (atn_code == 62)
+ {
+ if (varindx >= info->vars.alloc)
+ {
+ unsigned int alloc;
+
+ alloc = info->vars.alloc;
+ if (alloc == 0)
+ alloc = 4;
+ while (varindx >= alloc)
+ alloc *= 2;
+ info->vars.vars = ((struct ieee_var *)
+ xrealloc (info->vars.vars,
+ (alloc
+ * sizeof *info->vars.vars)));
+ memset (info->vars.vars + info->vars.alloc, 0,
+ ((alloc - info->vars.alloc)
+ * sizeof *info->vars.vars));
+ info->vars.alloc = alloc;
+ }
+
+ pvar = info->vars.vars + varindx;
+ pvar->name = "";
+ pvar->namlen = 0;
+ }
+ else
+ {
+ ieee_error (info, atn_start, "undefined variable in ATN");
+ return false;
+ }
+ }
+
+ pvar = info->vars.vars + varindx;
+
+ pvar->type = type;
+
+ name = pvar->name;
+ namlen = pvar->namlen;
+ }
+
+ dhandle = info->dhandle;
+
+ /* If we are going to call debug_record_variable with a pointer
+ type, change the type to an indirect type so that we can later
+ change it to a reference type if we encounter a C++ pmisc 'R'
+ record. */
+ if (pvar != NULL
+ && type != DEBUG_TYPE_NULL
+ && debug_get_type_kind (dhandle, type) == DEBUG_KIND_POINTER)
+ {
+ switch (atn_code)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ case 8:
+ case 10:
+ pvar->pslot = (debug_type *) xmalloc (sizeof *pvar->pslot);
+ *pvar->pslot = type;
+ type = debug_make_indirect_type (dhandle, pvar->pslot,
+ (const char *) NULL);
+ pvar->type = type;
+ break;
+ }
+ }
+
+ switch (atn_code)
+ {
+ default:
+ ieee_error (info, atn_code_start, "unknown ATN type");
+ return false;
+
+ case 1:
+ /* Automatic variable. */
+ if (! ieee_read_number (info, pp, &v))
+ return false;
+ namcopy = savestring (name, namlen);
+ if (type == NULL)
+ type = debug_make_void_type (dhandle);
+ if (pvar != NULL)
+ pvar->kind = IEEE_LOCAL;
+ return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v);
+
+ case 2:
+ /* Register variable. */
+ if (! ieee_read_number (info, pp, &v))
+ return false;
+ namcopy = savestring (name, namlen);
+ if (type == NULL)
+ type = debug_make_void_type (dhandle);
+ if (pvar != NULL)
+ pvar->kind = IEEE_LOCAL;
+ return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER,
+ ieee_regno_to_genreg (info->abfd, v));
+
+ case 3:
+ /* Static variable. */
+ if (! ieee_require_asn (info, pp, &v))
+ return false;
+ namcopy = savestring (name, namlen);
+ if (type == NULL)
+ type = debug_make_void_type (dhandle);
+ if (info->blockstack.bsp <= info->blockstack.stack)
+ blocktype = 0;
+ else
+ blocktype = info->blockstack.bsp[-1].kind;
+ if (pvar != NULL)
+ {
+ if (blocktype == 4 || blocktype == 6)
+ pvar->kind = IEEE_LOCAL;
+ else
+ pvar->kind = IEEE_STATIC;
+ }
+ return debug_record_variable (dhandle, namcopy, type,
+ (blocktype == 4 || blocktype == 6
+ ? DEBUG_LOCAL_STATIC
+ : DEBUG_STATIC),
+ v);
+
+ case 4:
+ /* External function. We don't currently record these. FIXME. */
+ if (pvar != NULL)
+ pvar->kind = IEEE_EXTERNAL;
+ return true;
+
+ case 5:
+ /* External variable. We don't currently record these. FIXME. */
+ if (pvar != NULL)
+ pvar->kind = IEEE_EXTERNAL;
+ return true;
+
+ case 7:
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_number (info, pp, &v2)
+ || ! ieee_read_optional_number (info, pp, &v3, &present))
+ return false;
+ if (present)
+ {
+ if (! ieee_read_optional_number (info, pp, &v4, &present))
+ return false;
+ }
+
+ /* We just ignore the two optional fields in v3 and v4, since
+ they are not defined. */
+
+ if (! ieee_require_asn (info, pp, &v3))
+ return false;
+
+ /* We have no way to record the column number. FIXME. */
+
+ return debug_record_line (dhandle, v, v3);
+
+ case 8:
+ /* Global variable. */
+ if (! ieee_require_asn (info, pp, &v))
+ return false;
+ namcopy = savestring (name, namlen);
+ if (type == NULL)
+ type = debug_make_void_type (dhandle);
+ if (pvar != NULL)
+ pvar->kind = IEEE_GLOBAL;
+ return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v);
+
+ case 9:
+ /* Variable lifetime information. */
+ if (! ieee_read_number (info, pp, &v))
+ return false;
+
+ /* We have no way to record this information. FIXME. */
+ return true;
+
+ case 10:
+ /* Locked register. The spec says that there are two required
+ fields, but at least on occasion the MRI compiler only emits
+ one. */
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_optional_number (info, pp, &v2, &present))
+ return false;
+
+ /* I think this means a variable that is both in a register and
+ a frame slot. We ignore the frame slot. FIXME. */
+
+ namcopy = savestring (name, namlen);
+ if (type == NULL)
+ type = debug_make_void_type (dhandle);
+ if (pvar != NULL)
+ pvar->kind = IEEE_LOCAL;
+ return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, v);
+
+ case 11:
+ /* Reserved for FORTRAN common. */
+ ieee_error (info, atn_code_start, "unsupported ATN11");
+
+ /* Return true to keep going. */
+ return true;
+
+ case 12:
+ /* Based variable. */
+ v3 = 0;
+ v4 = 0x80;
+ v5 = 0;
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_number (info, pp, &v2)
+ || ! ieee_read_optional_number (info, pp, &v3, &present))
+ return false;
+ if (present)
+ {
+ if (! ieee_read_optional_number (info, pp, &v4, &present))
+ return false;
+ if (present)
+ {
+ if (! ieee_read_optional_number (info, pp, &v5, &present))
+ return false;
+ }
+ }
+
+ /* We have no way to record this information. FIXME. */
+
+ ieee_error (info, atn_code_start, "unsupported ATN12");
+
+ /* Return true to keep going. */
+ return true;
+
+ case 16:
+ /* Constant. The description of this that I have is ambiguous,
+ so I'm not going to try to implement it. */
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_optional_number (info, pp, &v2, &present))
+ return false;
+ if (present)
+ {
+ if (! ieee_read_optional_number (info, pp, &v2, &present))
+ return false;
+ if (present)
+ {
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ }
+ }
+
+ if ((ieee_record_enum_type) **pp == ieee_e2_first_byte_enum)
+ {
+ if (! ieee_require_asn (info, pp, &v3))
+ return false;
+ }
+
+ return true;
+
+ case 19:
+ /* Static variable from assembler. */
+ v2 = 0;
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_optional_number (info, pp, &v2, &present)
+ || ! ieee_require_asn (info, pp, &v3))
+ return false;
+ namcopy = savestring (name, namlen);
+ /* We don't really handle this correctly. FIXME. */
+ return debug_record_variable (dhandle, namcopy,
+ debug_make_void_type (dhandle),
+ v2 != 0 ? DEBUG_GLOBAL : DEBUG_STATIC,
+ v3);
+
+ case 62:
+ /* Procedure miscellaneous information. */
+ case 63:
+ /* Variable miscellaneous information. */
+ case 64:
+ /* Module miscellaneous information. */
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_number (info, pp, &v2)
+ || ! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+
+ if (atn_code == 62 && v == 80)
+ {
+ if (present)
+ {
+ ieee_error (info, atn_code_start,
+ "unexpected string in C++ misc");
+ return false;
+ }
+ return ieee_read_cxx_misc (info, pp, v2);
+ }
+
+ /* We just ignore all of this stuff. FIXME. */
+
+ for (; v2 > 0; --v2)
+ {
+ switch ((ieee_record_enum_type) **pp)
+ {
+ default:
+ ieee_error (info, *pp, "bad misc record");
+ return false;
+
+ case ieee_at_record_enum:
+ if (! ieee_require_atn65 (info, pp, &name, &namlen))
+ return false;
+ break;
+
+ case ieee_e2_first_byte_enum:
+ if (! ieee_require_asn (info, pp, &v3))
+ return false;
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ /*NOTREACHED*/
+}
+
+/* Handle C++ debugging miscellaneous records. This is called for
+ procedure miscellaneous records of type 80. */
+
+static boolean
+ieee_read_cxx_misc (info, pp, count)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ unsigned long count;
+{
+ const bfd_byte *start;
+ bfd_vma category;
+
+ start = *pp;
+
+ /* Get the category of C++ misc record. */
+ if (! ieee_require_asn (info, pp, &category))
+ return false;
+ --count;
+
+ switch (category)
+ {
+ default:
+ ieee_error (info, start, "unrecognized C++ misc record");
+ return false;
+
+ case 'T':
+ if (! ieee_read_cxx_class (info, pp, count))
+ return false;
+ break;
+
+ case 'M':
+ {
+ bfd_vma flags;
+ const char *name;
+ unsigned long namlen;
+
+ /* The IEEE spec indicates that the 'M' record only has a
+ flags field. The MRI compiler also emits the name of the
+ function. */
+
+ if (! ieee_require_asn (info, pp, &flags))
+ return false;
+ if (*pp < info->pend
+ && (ieee_record_enum_type) **pp == ieee_at_record_enum)
+ {
+ if (! ieee_require_atn65 (info, pp, &name, &namlen))
+ return false;
+ }
+
+ /* This is emitted for method functions, but I don't think we
+ care very much. It might help if it told us useful
+ information like the class with which this function is
+ associated, but it doesn't, so it isn't helpful. */
+ }
+ break;
+
+ case 'B':
+ if (! ieee_read_cxx_defaults (info, pp, count))
+ return false;
+ break;
+
+ case 'z':
+ {
+ const char *name, *mangled, *class;
+ unsigned long namlen, mangledlen, classlen;
+ bfd_vma control;
+
+ /* Pointer to member. */
+
+ if (! ieee_require_atn65 (info, pp, &name, &namlen)
+ || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen)
+ || ! ieee_require_atn65 (info, pp, &class, &classlen)
+ || ! ieee_require_asn (info, pp, &control))
+ return false;
+
+ /* FIXME: We should now track down name and change its type. */
+ }
+ break;
+
+ case 'R':
+ if (! ieee_read_reference (info, pp))
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+/* Read a C++ class definition. This is a pmisc type 80 record of
+ category 'T'. */
+
+static boolean
+ieee_read_cxx_class (info, pp, count)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ unsigned long count;
+{
+ const bfd_byte *start;
+ bfd_vma class;
+ const char *tag;
+ unsigned long taglen;
+ struct ieee_tag *it;
+ PTR dhandle;
+ debug_field *fields;
+ unsigned int field_count, field_alloc;
+ debug_baseclass *baseclasses;
+ unsigned int baseclasses_count, baseclasses_alloc;
+ const debug_field *structfields;
+ struct ieee_method
+ {
+ const char *name;
+ unsigned long namlen;
+ debug_method_variant *variants;
+ unsigned count;
+ unsigned int alloc;
+ } *methods;
+ unsigned int methods_count, methods_alloc;
+ debug_type vptrbase;
+ boolean ownvptr;
+ debug_method *dmethods;
+
+ start = *pp;
+
+ if (! ieee_require_asn (info, pp, &class))
+ return false;
+ --count;
+
+ if (! ieee_require_atn65 (info, pp, &tag, &taglen))
+ return false;
+ --count;
+
+ /* Find the C struct with this name. */
+ for (it = info->tags; it != NULL; it = it->next)
+ if (it->name[0] == tag[0]
+ && strncmp (it->name, tag, taglen) == 0
+ && strlen (it->name) == taglen)
+ break;
+ if (it == NULL)
+ {
+ ieee_error (info, start, "undefined C++ object");
+ return false;
+ }
+
+ dhandle = info->dhandle;
+
+ fields = NULL;
+ field_count = 0;
+ field_alloc = 0;
+ baseclasses = NULL;
+ baseclasses_count = 0;
+ baseclasses_alloc = 0;
+ methods = NULL;
+ methods_count = 0;
+ methods_alloc = 0;
+ vptrbase = DEBUG_TYPE_NULL;
+ ownvptr = false;
+
+ structfields = debug_get_fields (dhandle, it->type);
+
+ while (count > 0)
+ {
+ bfd_vma id;
+ const bfd_byte *spec_start;
+
+ spec_start = *pp;
+
+ if (! ieee_require_asn (info, pp, &id))
+ return false;
+ --count;
+
+ switch (id)
+ {
+ default:
+ ieee_error (info, spec_start, "unrecognized C++ object spec");
+ return false;
+
+ case 'b':
+ {
+ bfd_vma flags, cinline;
+ const char *basename, *fieldname;
+ unsigned long baselen, fieldlen;
+ char *basecopy;
+ debug_type basetype;
+ bfd_vma bitpos;
+ boolean virtualp;
+ enum debug_visibility visibility;
+ debug_baseclass baseclass;
+
+ /* This represents a base or friend class. */
+
+ if (! ieee_require_asn (info, pp, &flags)
+ || ! ieee_require_atn65 (info, pp, &basename, &baselen)
+ || ! ieee_require_asn (info, pp, &cinline)
+ || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen))
+ return false;
+ count -= 4;
+
+ /* We have no way of recording friend information, so we
+ just ignore it. */
+ if ((flags & BASEFLAGS_FRIEND) != 0)
+ break;
+
+ /* I assume that either all of the members of the
+ baseclass are included in the object, starting at the
+ beginning of the object, or that none of them are
+ included. */
+
+ if ((fieldlen == 0) == (cinline == 0))
+ {
+ ieee_error (info, start, "unsupported C++ object type");
+ return false;
+ }
+
+ basecopy = savestring (basename, baselen);
+ basetype = debug_find_tagged_type (dhandle, basecopy,
+ DEBUG_KIND_ILLEGAL);
+ free (basecopy);
+ if (basetype == DEBUG_TYPE_NULL)
+ {
+ ieee_error (info, start, "C++ base class not defined");
+ return false;
+ }
+
+ if (fieldlen == 0)
+ bitpos = 0;
+ else
+ {
+ const debug_field *pf;
+
+ if (structfields == NULL)
+ {
+ ieee_error (info, start, "C++ object has no fields");
+ return false;
+ }
+
+ for (pf = structfields; *pf != DEBUG_FIELD_NULL; pf++)
+ {
+ const char *fname;
+
+ fname = debug_get_field_name (dhandle, *pf);
+ if (fname == NULL)
+ return false;
+ if (fname[0] == fieldname[0]
+ && strncmp (fname, fieldname, fieldlen) == 0
+ && strlen (fname) == fieldlen)
+ break;
+ }
+ if (*pf == DEBUG_FIELD_NULL)
+ {
+ ieee_error (info, start,
+ "C++ base class not found in container");
+ return false;
+ }
+
+ bitpos = debug_get_field_bitpos (dhandle, *pf);
+ }
+
+ if ((flags & BASEFLAGS_VIRTUAL) != 0)
+ virtualp = true;
+ else
+ virtualp = false;
+ if ((flags & BASEFLAGS_PRIVATE) != 0)
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ else
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+
+ baseclass = debug_make_baseclass (dhandle, basetype, bitpos,
+ virtualp, visibility);
+ if (baseclass == DEBUG_BASECLASS_NULL)
+ return false;
+
+ if (baseclasses_count + 1 >= baseclasses_alloc)
+ {
+ baseclasses_alloc += 10;
+ baseclasses = ((debug_baseclass *)
+ xrealloc (baseclasses,
+ (baseclasses_alloc
+ * sizeof *baseclasses)));
+ }
+
+ baseclasses[baseclasses_count] = baseclass;
+ ++baseclasses_count;
+ baseclasses[baseclasses_count] = DEBUG_BASECLASS_NULL;
+ }
+ break;
+
+ case 'd':
+ {
+ bfd_vma flags;
+ const char *fieldname, *mangledname;
+ unsigned long fieldlen, mangledlen;
+ char *fieldcopy;
+ boolean staticp;
+ debug_type ftype;
+ const debug_field *pf;
+ enum debug_visibility visibility;
+ debug_field field;
+
+ /* This represents a data member. */
+
+ if (! ieee_require_asn (info, pp, &flags)
+ || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen)
+ || ! ieee_require_atn65 (info, pp, &mangledname, &mangledlen))
+ return false;
+ count -= 3;
+
+ fieldcopy = savestring (fieldname, fieldlen);
+
+ staticp = (flags & CXXFLAGS_STATIC) != 0 ? true : false;
+
+ if (staticp)
+ {
+ struct ieee_var *pv, *pvend;
+
+ /* See if we can find a definition for this variable. */
+ pv = info->vars.vars;
+ pvend = pv + info->vars.alloc;
+ for (; pv < pvend; pv++)
+ if (pv->namlen == mangledlen
+ && strncmp (pv->name, mangledname, mangledlen) == 0)
+ break;
+ if (pv < pvend)
+ ftype = pv->type;
+ else
+ {
+ /* This can happen if the variable is never used. */
+ ftype = ieee_builtin_type (info, start,
+ (unsigned int) builtin_void);
+ }
+ }
+ else
+ {
+ unsigned int findx;
+
+ if (structfields == NULL)
+ {
+ ieee_error (info, start, "C++ object has no fields");
+ return false;
+ }
+
+ for (pf = structfields, findx = 0;
+ *pf != DEBUG_FIELD_NULL;
+ pf++, findx++)
+ {
+ const char *fname;
+
+ fname = debug_get_field_name (dhandle, *pf);
+ if (fname == NULL)
+ return false;
+ if (fname[0] == mangledname[0]
+ && strncmp (fname, mangledname, mangledlen) == 0
+ && strlen (fname) == mangledlen)
+ break;
+ }
+ if (*pf == DEBUG_FIELD_NULL)
+ {
+ ieee_error (info, start,
+ "C++ data member not found in container");
+ return false;
+ }
+
+ ftype = debug_get_field_type (dhandle, *pf);
+
+ if (debug_get_type_kind (dhandle, ftype) == DEBUG_KIND_POINTER)
+ {
+ /* We might need to convert this field into a
+ reference type later on, so make it an indirect
+ type. */
+ if (it->fslots == NULL)
+ {
+ unsigned int fcnt;
+ const debug_field *pfcnt;
+
+ fcnt = 0;
+ for (pfcnt = structfields;
+ *pfcnt != DEBUG_FIELD_NULL;
+ pfcnt++)
+ ++fcnt;
+ it->fslots = ((debug_type *)
+ xmalloc (fcnt * sizeof *it->fslots));
+ memset (it->fslots, 0,
+ fcnt * sizeof *it->fslots);
+ }
+
+ if (ftype == DEBUG_TYPE_NULL)
+ return false;
+ it->fslots[findx] = ftype;
+ ftype = debug_make_indirect_type (dhandle,
+ it->fslots + findx,
+ (const char *) NULL);
+ }
+ }
+ if (ftype == DEBUG_TYPE_NULL)
+ return false;
+
+ switch (flags & CXXFLAGS_VISIBILITY)
+ {
+ default:
+ ieee_error (info, start, "unknown C++ visibility");
+ return false;
+
+ case CXXFLAGS_VISIBILITY_PUBLIC:
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+
+ case CXXFLAGS_VISIBILITY_PRIVATE:
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ break;
+
+ case CXXFLAGS_VISIBILITY_PROTECTED:
+ visibility = DEBUG_VISIBILITY_PROTECTED;
+ break;
+ }
+
+ if (staticp)
+ {
+ char *mangledcopy;
+
+ mangledcopy = savestring (mangledname, mangledlen);
+
+ field = debug_make_static_member (dhandle, fieldcopy,
+ ftype, mangledcopy,
+ visibility);
+ }
+ else
+ {
+ bfd_vma bitpos, bitsize;
+
+ bitpos = debug_get_field_bitpos (dhandle, *pf);
+ bitsize = debug_get_field_bitsize (dhandle, *pf);
+ if (bitpos == (bfd_vma) -1 || bitsize == (bfd_vma) -1)
+ {
+ ieee_error (info, start, "bad C++ field bit pos or size");
+ return false;
+ }
+ field = debug_make_field (dhandle, fieldcopy, ftype, bitpos,
+ bitsize, visibility);
+ }
+
+ if (field == DEBUG_FIELD_NULL)
+ return false;
+
+ if (field_count + 1 >= field_alloc)
+ {
+ field_alloc += 10;
+ fields = ((debug_field *)
+ xrealloc (fields, field_alloc * sizeof *fields));
+ }
+
+ fields[field_count] = field;
+ ++field_count;
+ fields[field_count] = DEBUG_FIELD_NULL;
+ }
+ break;
+
+ case 'm':
+ case 'v':
+ {
+ bfd_vma flags, voffset, control;
+ const char *name, *mangled;
+ unsigned long namlen, mangledlen;
+ struct ieee_var *pv, *pvend;
+ debug_type type;
+ enum debug_visibility visibility;
+ boolean constp, volatilep;
+ char *mangledcopy;
+ debug_method_variant mv;
+ struct ieee_method *meth;
+ unsigned int im;
+
+ if (! ieee_require_asn (info, pp, &flags)
+ || ! ieee_require_atn65 (info, pp, &name, &namlen)
+ || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
+ return false;
+ count -= 3;
+ if (id != 'v')
+ voffset = 0;
+ else
+ {
+ if (! ieee_require_asn (info, pp, &voffset))
+ return false;
+ --count;
+ }
+ if (! ieee_require_asn (info, pp, &control))
+ return false;
+ --count;
+
+ /* We just ignore the control information. */
+
+ /* We have no way to represent friend information, so we
+ just ignore it. */
+ if ((flags & CXXFLAGS_FRIEND) != 0)
+ break;
+
+ /* We should already have seen a type for the function. */
+ pv = info->vars.vars;
+ pvend = pv + info->vars.alloc;
+ for (; pv < pvend; pv++)
+ if (pv->namlen == mangledlen
+ && strncmp (pv->name, mangled, mangledlen) == 0)
+ break;
+
+ if (pv >= pvend)
+ {
+ /* We won't have type information for this function if
+ it is not included in this file. We don't try to
+ handle this case. FIXME. */
+ type = (debug_make_function_type
+ (dhandle,
+ ieee_builtin_type (info, start,
+ (unsigned int) builtin_void),
+ (debug_type *) NULL,
+ false));
+ }
+ else
+ {
+ debug_type return_type;
+ const debug_type *arg_types;
+ boolean varargs;
+
+ if (debug_get_type_kind (dhandle, pv->type)
+ != DEBUG_KIND_FUNCTION)
+ {
+ ieee_error (info, start,
+ "bad type for C++ method function");
+ return false;
+ }
+
+ return_type = debug_get_return_type (dhandle, pv->type);
+ arg_types = debug_get_parameter_types (dhandle, pv->type,
+ &varargs);
+ if (return_type == DEBUG_TYPE_NULL || arg_types == NULL)
+ {
+ ieee_error (info, start,
+ "no type information for C++ method function");
+ return false;
+ }
+
+ type = debug_make_method_type (dhandle, return_type, it->type,
+ (debug_type *) arg_types,
+ varargs);
+ }
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ switch (flags & CXXFLAGS_VISIBILITY)
+ {
+ default:
+ ieee_error (info, start, "unknown C++ visibility");
+ return false;
+
+ case CXXFLAGS_VISIBILITY_PUBLIC:
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+
+ case CXXFLAGS_VISIBILITY_PRIVATE:
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ break;
+
+ case CXXFLAGS_VISIBILITY_PROTECTED:
+ visibility = DEBUG_VISIBILITY_PROTECTED;
+ break;
+ }
+
+ constp = (flags & CXXFLAGS_CONST) != 0 ? true : false;
+ volatilep = (flags & CXXFLAGS_VOLATILE) != 0 ? true : false;
+
+ mangledcopy = savestring (mangled, mangledlen);
+
+ if ((flags & CXXFLAGS_STATIC) != 0)
+ {
+ if (id == 'v')
+ {
+ ieee_error (info, start, "C++ static virtual method");
+ return false;
+ }
+ mv = debug_make_static_method_variant (dhandle, mangledcopy,
+ type, visibility,
+ constp, volatilep);
+ }
+ else
+ {
+ debug_type vcontext;
+
+ if (id != 'v')
+ vcontext = DEBUG_TYPE_NULL;
+ else
+ {
+ /* FIXME: How can we calculate this correctly? */
+ vcontext = it->type;
+ }
+ mv = debug_make_method_variant (dhandle, mangledcopy, type,
+ visibility, constp,
+ volatilep, voffset,
+ vcontext);
+ }
+ if (mv == DEBUG_METHOD_VARIANT_NULL)
+ return false;
+
+ for (meth = methods, im = 0; im < methods_count; meth++, im++)
+ if (meth->namlen == namlen
+ && strncmp (meth->name, name, namlen) == 0)
+ break;
+ if (im >= methods_count)
+ {
+ if (methods_count >= methods_alloc)
+ {
+ methods_alloc += 10;
+ methods = ((struct ieee_method *)
+ xrealloc (methods,
+ methods_alloc * sizeof *methods));
+ }
+ methods[methods_count].name = name;
+ methods[methods_count].namlen = namlen;
+ methods[methods_count].variants = NULL;
+ methods[methods_count].count = 0;
+ methods[methods_count].alloc = 0;
+ meth = methods + methods_count;
+ ++methods_count;
+ }
+
+ if (meth->count + 1 >= meth->alloc)
+ {
+ meth->alloc += 10;
+ meth->variants = ((debug_method_variant *)
+ xrealloc (meth->variants,
+ (meth->alloc
+ * sizeof *meth->variants)));
+ }
+
+ meth->variants[meth->count] = mv;
+ ++meth->count;
+ meth->variants[meth->count] = DEBUG_METHOD_VARIANT_NULL;
+ }
+ break;
+
+ case 'o':
+ {
+ bfd_vma spec;
+
+ /* We have no way to store this information, so we just
+ ignore it. */
+ if (! ieee_require_asn (info, pp, &spec))
+ return false;
+ --count;
+ if ((spec & 4) != 0)
+ {
+ const char *filename;
+ unsigned long filenamlen;
+ bfd_vma lineno;
+
+ if (! ieee_require_atn65 (info, pp, &filename, &filenamlen)
+ || ! ieee_require_asn (info, pp, &lineno))
+ return false;
+ count -= 2;
+ }
+ else if ((spec & 8) != 0)
+ {
+ const char *mangled;
+ unsigned long mangledlen;
+
+ if (! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
+ return false;
+ --count;
+ }
+ else
+ {
+ ieee_error (info, start,
+ "unrecognized C++ object overhead spec");
+ return false;
+ }
+ }
+ break;
+
+ case 'z':
+ {
+ const char *vname, *basename;
+ unsigned long vnamelen, baselen;
+ bfd_vma vsize, control;
+
+ /* A virtual table pointer. */
+
+ if (! ieee_require_atn65 (info, pp, &vname, &vnamelen)
+ || ! ieee_require_asn (info, pp, &vsize)
+ || ! ieee_require_atn65 (info, pp, &basename, &baselen)
+ || ! ieee_require_asn (info, pp, &control))
+ return false;
+ count -= 4;
+
+ /* We just ignore the control number. We don't care what
+ the virtual table name is. We have no way to store the
+ virtual table size, and I don't think we care anyhow. */
+
+ /* FIXME: We can't handle multiple virtual table pointers. */
+
+ if (baselen == 0)
+ ownvptr = true;
+ else
+ {
+ char *basecopy;
+
+ basecopy = savestring (basename, baselen);
+ vptrbase = debug_find_tagged_type (dhandle, basecopy,
+ DEBUG_KIND_ILLEGAL);
+ free (basecopy);
+ if (vptrbase == DEBUG_TYPE_NULL)
+ {
+ ieee_error (info, start, "undefined C++ vtable");
+ return false;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ /* Now that we have seen all the method variants, we can call
+ debug_make_method for each one. */
+
+ if (methods_count == 0)
+ dmethods = NULL;
+ else
+ {
+ unsigned int i;
+
+ dmethods = ((debug_method *)
+ xmalloc ((methods_count + 1) * sizeof *dmethods));
+ for (i = 0; i < methods_count; i++)
+ {
+ char *namcopy;
+
+ namcopy = savestring (methods[i].name, methods[i].namlen);
+ dmethods[i] = debug_make_method (dhandle, namcopy,
+ methods[i].variants);
+ if (dmethods[i] == DEBUG_METHOD_NULL)
+ return false;
+ }
+ dmethods[i] = DEBUG_METHOD_NULL;
+ free (methods);
+ }
+
+ /* The struct type was created as an indirect type pointing at
+ it->slot. We update it->slot to automatically update all
+ references to this struct. */
+ it->slot = debug_make_object_type (dhandle,
+ class != 'u',
+ debug_get_type_size (dhandle,
+ it->slot),
+ fields, baseclasses, dmethods,
+ vptrbase, ownvptr);
+ if (it->slot == DEBUG_TYPE_NULL)
+ return false;
+
+ return true;
+}
+
+/* Read C++ default argument value and reference type information. */
+
+static boolean
+ieee_read_cxx_defaults (info, pp, count)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ unsigned long count;
+{
+ const bfd_byte *start;
+ const char *fnname;
+ unsigned long fnlen;
+ bfd_vma defcount;
+
+ start = *pp;
+
+ /* Giving the function name before the argument count is an addendum
+ to the spec. The function name is demangled, though, so this
+ record must always refer to the current function. */
+
+ if (info->blockstack.bsp <= info->blockstack.stack
+ || info->blockstack.bsp[-1].fnindx == (unsigned int) -1)
+ {
+ ieee_error (info, start, "C++ default values not in a function");
+ return false;
+ }
+
+ if (! ieee_require_atn65 (info, pp, &fnname, &fnlen)
+ || ! ieee_require_asn (info, pp, &defcount))
+ return false;
+ count -= 2;
+
+ while (defcount-- > 0)
+ {
+ bfd_vma type, val;
+ const char *strval;
+ unsigned long strvallen;
+
+ if (! ieee_require_asn (info, pp, &type))
+ return false;
+ --count;
+
+ switch (type)
+ {
+ case 0:
+ case 4:
+ break;
+
+ case 1:
+ case 2:
+ if (! ieee_require_asn (info, pp, &val))
+ return false;
+ --count;
+ break;
+
+ case 3:
+ case 7:
+ if (! ieee_require_atn65 (info, pp, &strval, &strvallen))
+ return false;
+ --count;
+ break;
+
+ default:
+ ieee_error (info, start, "unrecognized C++ default type");
+ return false;
+ }
+
+ /* We have no way to record the default argument values, so we
+ just ignore them. FIXME. */
+ }
+
+ /* Any remaining arguments are indices of parameters that are really
+ reference type. */
+ if (count > 0)
+ {
+ PTR dhandle;
+ debug_type *arg_slots;
+
+ dhandle = info->dhandle;
+ arg_slots = info->types.types[info->blockstack.bsp[-1].fnindx].arg_slots;
+ while (count-- > 0)
+ {
+ bfd_vma indx;
+ debug_type target;
+
+ if (! ieee_require_asn (info, pp, &indx))
+ return false;
+ /* The index is 1 based. */
+ --indx;
+ if (arg_slots == NULL
+ || arg_slots[indx] == DEBUG_TYPE_NULL
+ || (debug_get_type_kind (dhandle, arg_slots[indx])
+ != DEBUG_KIND_POINTER))
+ {
+ ieee_error (info, start, "reference parameter is not a pointer");
+ return false;
+ }
+
+ target = debug_get_target_type (dhandle, arg_slots[indx]);
+ arg_slots[indx] = debug_make_reference_type (dhandle, target);
+ if (arg_slots[indx] == DEBUG_TYPE_NULL)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Read a C++ reference definition. */
+
+static boolean
+ieee_read_reference (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ const bfd_byte *start;
+ bfd_vma flags;
+ const char *class, *name;
+ unsigned long classlen, namlen;
+ debug_type *pslot;
+ debug_type target;
+
+ start = *pp;
+
+ if (! ieee_require_asn (info, pp, &flags))
+ return false;
+
+ /* Giving the class name before the member name is in an addendum to
+ the spec. */
+ if (flags == 3)
+ {
+ if (! ieee_require_atn65 (info, pp, &class, &classlen))
+ return false;
+ }
+
+ if (! ieee_require_atn65 (info, pp, &name, &namlen))
+ return false;
+
+ pslot = NULL;
+ if (flags != 3)
+ {
+ int pass;
+
+ /* We search from the last variable indices to the first in
+ hopes of finding local variables correctly. We search the
+ local variables on the first pass, and the global variables
+ on the second. FIXME: This probably won't work in all cases.
+ On the other hand, I don't know what will. */
+ for (pass = 0; pass < 2; pass++)
+ {
+ struct ieee_vars *vars;
+ int i;
+ struct ieee_var *pv = NULL;
+
+ if (pass == 0)
+ vars = &info->vars;
+ else
+ {
+ vars = info->global_vars;
+ if (vars == NULL)
+ break;
+ }
+
+ for (i = (int) vars->alloc - 1; i >= 0; i--)
+ {
+ boolean found;
+
+ pv = vars->vars + i;
+
+ if (pv->pslot == NULL
+ || pv->namlen != namlen
+ || strncmp (pv->name, name, namlen) != 0)
+ continue;
+
+ found = false;
+ switch (flags)
+ {
+ default:
+ ieee_error (info, start,
+ "unrecognized C++ reference type");
+ return false;
+
+ case 0:
+ /* Global variable or function. */
+ if (pv->kind == IEEE_GLOBAL
+ || pv->kind == IEEE_EXTERNAL
+ || pv->kind == IEEE_FUNCTION)
+ found = true;
+ break;
+
+ case 1:
+ /* Global static variable or function. */
+ if (pv->kind == IEEE_STATIC
+ || pv->kind == IEEE_FUNCTION)
+ found = true;
+ break;
+
+ case 2:
+ /* Local variable. */
+ if (pv->kind == IEEE_LOCAL)
+ found = true;
+ break;
+ }
+
+ if (found)
+ break;
+ }
+
+ if (i >= 0)
+ {
+ pslot = pv->pslot;
+ break;
+ }
+ }
+ }
+ else
+ {
+ struct ieee_tag *it;
+
+ for (it = info->tags; it != NULL; it = it->next)
+ {
+ if (it->name[0] == class[0]
+ && strncmp (it->name, class, classlen) == 0
+ && strlen (it->name) == classlen)
+ {
+ if (it->fslots != NULL)
+ {
+ const debug_field *pf;
+ unsigned int findx;
+
+ pf = debug_get_fields (info->dhandle, it->type);
+ if (pf == NULL)
+ {
+ ieee_error (info, start,
+ "C++ reference in class with no fields");
+ return false;
+ }
+
+ for (findx = 0; *pf != DEBUG_FIELD_NULL; pf++, findx++)
+ {
+ const char *fname;
+
+ fname = debug_get_field_name (info->dhandle, *pf);
+ if (fname == NULL)
+ return false;
+ if (strncmp (fname, name, namlen) == 0
+ && strlen (fname) == namlen)
+ {
+ pslot = it->fslots + findx;
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (pslot == NULL)
+ {
+ ieee_error (info, start, "C++ reference not found");
+ return false;
+ }
+
+ /* We allocated the type of the object as an indirect type pointing
+ to *pslot, which we can now update to be a reference type. */
+ if (debug_get_type_kind (info->dhandle, *pslot) != DEBUG_KIND_POINTER)
+ {
+ ieee_error (info, start, "C++ reference is not pointer");
+ return false;
+ }
+
+ target = debug_get_target_type (info->dhandle, *pslot);
+ *pslot = debug_make_reference_type (info->dhandle, target);
+ if (*pslot == DEBUG_TYPE_NULL)
+ return false;
+
+ return true;
+}
+
+/* Require an ASN record. */
+
+static boolean
+ieee_require_asn (info, pp, pv)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ bfd_vma *pv;
+{
+ const bfd_byte *start;
+ ieee_record_enum_type c;
+ bfd_vma varindx;
+
+ start = *pp;
+
+ c = (ieee_record_enum_type) **pp;
+ if (c != ieee_e2_first_byte_enum)
+ {
+ ieee_error (info, start, "missing required ASN");
+ return false;
+ }
+ ++*pp;
+
+ c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
+ if (c != ieee_asn_record_enum)
+ {
+ ieee_error (info, start, "missing required ASN");
+ return false;
+ }
+ ++*pp;
+
+ /* Just ignore the variable index. */
+ if (! ieee_read_number (info, pp, &varindx))
+ return false;
+
+ return ieee_read_expression (info, pp, pv);
+}
+
+/* Require an ATN65 record. */
+
+static boolean
+ieee_require_atn65 (info, pp, pname, pnamlen)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ const char **pname;
+ unsigned long *pnamlen;
+{
+ const bfd_byte *start;
+ ieee_record_enum_type c;
+ bfd_vma name_indx, type_indx, atn_code;
+
+ start = *pp;
+
+ c = (ieee_record_enum_type) **pp;
+ if (c != ieee_at_record_enum)
+ {
+ ieee_error (info, start, "missing required ATN65");
+ return false;
+ }
+ ++*pp;
+
+ c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
+ if (c != ieee_atn_record_enum)
+ {
+ ieee_error (info, start, "missing required ATN65");
+ return false;
+ }
+ ++*pp;
+
+ if (! ieee_read_number (info, pp, &name_indx)
+ || ! ieee_read_number (info, pp, &type_indx)
+ || ! ieee_read_number (info, pp, &atn_code))
+ return false;
+
+ /* Just ignore name_indx. */
+
+ if (type_indx != 0 || atn_code != 65)
+ {
+ ieee_error (info, start, "bad ATN65 record");
+ return false;
+ }
+
+ return ieee_read_id (info, pp, pname, pnamlen);
+}
+
+/* Convert a register number in IEEE debugging information into a
+ generic register number. */
+
+static int
+ieee_regno_to_genreg (abfd, r)
+ bfd *abfd;
+ int r;
+{
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_m68k:
+ /* For some reasons stabs adds 2 to the floating point register
+ numbers. */
+ if (r >= 16)
+ r += 2;
+ break;
+
+ case bfd_arch_i960:
+ /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and
+ 32 to 35 for fp0 to fp3. */
+ --r;
+ break;
+
+ default:
+ break;
+ }
+
+ return r;
+}
+
+/* Convert a generic register number to an IEEE specific one. */
+
+static int
+ieee_genreg_to_regno (abfd, r)
+ bfd *abfd;
+ int r;
+{
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_m68k:
+ /* For some reason stabs add 2 to the floating point register
+ numbers. */
+ if (r >= 18)
+ r -= 2;
+ break;
+
+ case bfd_arch_i960:
+ /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and
+ 32 to 35 for fp0 to fp3. */
+ ++r;
+ break;
+
+ default:
+ break;
+ }
+
+ return r;
+}
+
+/* These routines build IEEE debugging information out of the generic
+ debugging information. */
+
+/* We build the IEEE debugging information byte by byte. Rather than
+ waste time copying data around, we use a linked list of buffers to
+ hold the data. */
+
+#define IEEE_BUFSIZE (490)
+
+struct ieee_buf
+{
+ /* Next buffer. */
+ struct ieee_buf *next;
+ /* Number of data bytes in this buffer. */
+ unsigned int c;
+ /* Bytes. */
+ bfd_byte buf[IEEE_BUFSIZE];
+};
+
+/* A list of buffers. */
+
+struct ieee_buflist
+{
+ /* Head of list. */
+ struct ieee_buf *head;
+ /* Tail--last buffer on list. */
+ struct ieee_buf *tail;
+};
+
+/* In order to generate the BB11 blocks required by the HP emulator,
+ we keep track of ranges of addresses which correspond to a given
+ compilation unit. */
+
+struct ieee_range
+{
+ /* Next range. */
+ struct ieee_range *next;
+ /* Low address. */
+ bfd_vma low;
+ /* High address. */
+ bfd_vma high;
+};
+
+/* This structure holds information for a class on the type stack. */
+
+struct ieee_type_class
+{
+ /* The name index in the debugging information. */
+ unsigned int indx;
+ /* The pmisc records for the class. */
+ struct ieee_buflist pmiscbuf;
+ /* The number of pmisc records. */
+ unsigned int pmisccount;
+ /* The name of the class holding the virtual table, if not this
+ class. */
+ const char *vclass;
+ /* Whether this class holds its own virtual table. */
+ boolean ownvptr;
+ /* The largest virtual table offset seen so far. */
+ bfd_vma voffset;
+ /* The current method. */
+ const char *method;
+ /* Additional pmisc records used to record fields of reference type. */
+ struct ieee_buflist refs;
+};
+
+/* This is how we store types for the writing routines. Most types
+ are simply represented by a type index. */
+
+struct ieee_write_type
+{
+ /* Type index. */
+ unsigned int indx;
+ /* The size of the type, if known. */
+ unsigned int size;
+ /* The name of the type, if any. */
+ const char *name;
+ /* If this is a function or method type, we build the type here, and
+ only add it to the output buffers if we need it. */
+ struct ieee_buflist fndef;
+ /* If this is a struct, this is where the struct definition is
+ built. */
+ struct ieee_buflist strdef;
+ /* If this is a class, this is where the class information is built. */
+ struct ieee_type_class *classdef;
+ /* Whether the type is unsigned. */
+ unsigned int unsignedp : 1;
+ /* Whether this is a reference type. */
+ unsigned int referencep : 1;
+ /* Whether this is in the local type block. */
+ unsigned int localp : 1;
+ /* Whether this is a duplicate struct definition which we are
+ ignoring. */
+ unsigned int ignorep : 1;
+};
+
+/* This is the type stack used by the debug writing routines. FIXME:
+ We could generate more efficient output if we remembered when we
+ have output a particular type before. */
+
+struct ieee_type_stack
+{
+ /* Next entry on stack. */
+ struct ieee_type_stack *next;
+ /* Type information. */
+ struct ieee_write_type type;
+};
+
+/* This is a list of associations between a name and some types.
+ These are used for typedefs and tags. */
+
+struct ieee_name_type
+{
+ /* Next type for this name. */
+ struct ieee_name_type *next;
+ /* ID number. For a typedef, this is the index of the type to which
+ this name is typedefed. */
+ unsigned int id;
+ /* Type. */
+ struct ieee_write_type type;
+ /* If this is a tag which has not yet been defined, this is the
+ kind. If the tag has been defined, this is DEBUG_KIND_ILLEGAL. */
+ enum debug_type_kind kind;
+};
+
+/* We use a hash table to associate names and types. */
+
+struct ieee_name_type_hash_table
+{
+ struct bfd_hash_table root;
+};
+
+struct ieee_name_type_hash_entry
+{
+ struct bfd_hash_entry root;
+ /* Information for this name. */
+ struct ieee_name_type *types;
+};
+
+/* This is a list of enums. */
+
+struct ieee_defined_enum
+{
+ /* Next enum. */
+ struct ieee_defined_enum *next;
+ /* Type index. */
+ unsigned int indx;
+ /* Tag. */
+ const char *tag;
+ /* Names. */
+ const char **names;
+ /* Values. */
+ bfd_signed_vma *vals;
+};
+
+/* We keep a list of modified versions of types, so that we don't
+ output them more than once. */
+
+struct ieee_modified_type
+{
+ /* Pointer to this type. */
+ unsigned int pointer;
+ /* Function with unknown arguments returning this type. */
+ unsigned int function;
+ /* Const version of this type. */
+ unsigned int const_qualified;
+ /* Volatile version of this type. */
+ unsigned int volatile_qualified;
+ /* List of arrays of this type of various bounds. */
+ struct ieee_modified_array_type *arrays;
+};
+
+/* A list of arrays bounds. */
+
+struct ieee_modified_array_type
+{
+ /* Next array bounds. */
+ struct ieee_modified_array_type *next;
+ /* Type index with these bounds. */
+ unsigned int indx;
+ /* Low bound. */
+ bfd_signed_vma low;
+ /* High bound. */
+ bfd_signed_vma high;
+};
+
+/* This is a list of pending function parameter information. We don't
+ output them until we see the first block. */
+
+struct ieee_pending_parm
+{
+ /* Next pending parameter. */
+ struct ieee_pending_parm *next;
+ /* Name. */
+ const char *name;
+ /* Type index. */
+ unsigned int type;
+ /* Whether the type is a reference. */
+ boolean referencep;
+ /* Kind. */
+ enum debug_parm_kind kind;
+ /* Value. */
+ bfd_vma val;
+};
+
+/* This is the handle passed down by debug_write. */
+
+struct ieee_handle
+{
+ /* BFD we are writing to. */
+ bfd *abfd;
+ /* Whether we got an error in a subroutine called via traverse or
+ map_over_sections. */
+ boolean error;
+ /* Current data buffer list. */
+ struct ieee_buflist *current;
+ /* Current data buffer. */
+ struct ieee_buf *curbuf;
+ /* Filename of current compilation unit. */
+ const char *filename;
+ /* Module name of current compilation unit. */
+ const char *modname;
+ /* List of buffer for global types. */
+ struct ieee_buflist global_types;
+ /* List of finished data buffers. */
+ struct ieee_buflist data;
+ /* List of buffers for typedefs in the current compilation unit. */
+ struct ieee_buflist types;
+ /* List of buffers for variables and functions in the current
+ compilation unit. */
+ struct ieee_buflist vars;
+ /* List of buffers for C++ class definitions in the current
+ compilation unit. */
+ struct ieee_buflist cxx;
+ /* List of buffers for line numbers in the current compilation unit. */
+ struct ieee_buflist linenos;
+ /* Ranges for the current compilation unit. */
+ struct ieee_range *ranges;
+ /* Ranges for all debugging information. */
+ struct ieee_range *global_ranges;
+ /* Nested pending ranges. */
+ struct ieee_range *pending_ranges;
+ /* Type stack. */
+ struct ieee_type_stack *type_stack;
+ /* Next unallocated type index. */
+ unsigned int type_indx;
+ /* Next unallocated name index. */
+ unsigned int name_indx;
+ /* Typedefs. */
+ struct ieee_name_type_hash_table typedefs;
+ /* Tags. */
+ struct ieee_name_type_hash_table tags;
+ /* Enums. */
+ struct ieee_defined_enum *enums;
+ /* Modified versions of types. */
+ struct ieee_modified_type *modified;
+ /* Number of entries allocated in modified. */
+ unsigned int modified_alloc;
+ /* 4 byte complex type. */
+ unsigned int complex_float_index;
+ /* 8 byte complex type. */
+ unsigned int complex_double_index;
+ /* The depth of block nesting. This is 0 outside a function, and 1
+ just after start_function is called. */
+ unsigned int block_depth;
+ /* The name of the current function. */
+ const char *fnname;
+ /* List of buffers for the type of the function we are currently
+ writing out. */
+ struct ieee_buflist fntype;
+ /* List of buffers for the parameters of the function we are
+ currently writing out. */
+ struct ieee_buflist fnargs;
+ /* Number of arguments written to fnargs. */
+ unsigned int fnargcount;
+ /* Pending function parameters. */
+ struct ieee_pending_parm *pending_parms;
+ /* Current line number filename. */
+ const char *lineno_filename;
+ /* Line number name index. */
+ unsigned int lineno_name_indx;
+ /* Filename of pending line number. */
+ const char *pending_lineno_filename;
+ /* Pending line number. */
+ unsigned long pending_lineno;
+ /* Address of pending line number. */
+ bfd_vma pending_lineno_addr;
+ /* Highest address seen at end of procedure. */
+ bfd_vma highaddr;
+};
+
+static boolean ieee_init_buffer
+ PARAMS ((struct ieee_handle *, struct ieee_buflist *));
+static boolean ieee_change_buffer
+ PARAMS ((struct ieee_handle *, struct ieee_buflist *));
+static boolean ieee_append_buffer
+ PARAMS ((struct ieee_handle *, struct ieee_buflist *,
+ struct ieee_buflist *));
+static boolean ieee_real_write_byte PARAMS ((struct ieee_handle *, int));
+static boolean ieee_write_2bytes PARAMS ((struct ieee_handle *, int));
+static boolean ieee_write_number PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_write_id PARAMS ((struct ieee_handle *, const char *));
+static boolean ieee_write_asn
+ PARAMS ((struct ieee_handle *, unsigned int, bfd_vma));
+static boolean ieee_write_atn65
+ PARAMS ((struct ieee_handle *, unsigned int, const char *));
+static boolean ieee_push_type
+ PARAMS ((struct ieee_handle *, unsigned int, unsigned int, boolean,
+ boolean));
+static unsigned int ieee_pop_type PARAMS ((struct ieee_handle *));
+static void ieee_pop_unused_type PARAMS ((struct ieee_handle *));
+static unsigned int ieee_pop_type_used
+ PARAMS ((struct ieee_handle *, boolean));
+static boolean ieee_add_range
+ PARAMS ((struct ieee_handle *, boolean, bfd_vma, bfd_vma));
+static boolean ieee_start_range PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_end_range PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_define_type
+ PARAMS ((struct ieee_handle *, unsigned int, boolean, boolean));
+static boolean ieee_define_named_type
+ PARAMS ((struct ieee_handle *, const char *, unsigned int, unsigned int,
+ boolean, boolean, struct ieee_buflist *));
+static struct ieee_modified_type *ieee_get_modified_info
+ PARAMS ((struct ieee_handle *, unsigned int));
+static struct bfd_hash_entry *ieee_name_type_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static boolean ieee_write_undefined_tag
+ PARAMS ((struct ieee_name_type_hash_entry *, PTR));
+static boolean ieee_finish_compilation_unit PARAMS ((struct ieee_handle *));
+static void ieee_add_bb11_blocks PARAMS ((bfd *, asection *, PTR));
+static boolean ieee_add_bb11
+ PARAMS ((struct ieee_handle *, asection *, bfd_vma, bfd_vma));
+static boolean ieee_output_pending_parms PARAMS ((struct ieee_handle *));
+static unsigned int ieee_vis_to_flags PARAMS ((enum debug_visibility));
+static boolean ieee_class_method_var
+ PARAMS ((struct ieee_handle *, const char *, enum debug_visibility, boolean,
+ boolean, boolean, bfd_vma, boolean));
+
+static boolean ieee_start_compilation_unit PARAMS ((PTR, const char *));
+static boolean ieee_start_source PARAMS ((PTR, const char *));
+static boolean ieee_empty_type PARAMS ((PTR));
+static boolean ieee_void_type PARAMS ((PTR));
+static boolean ieee_int_type PARAMS ((PTR, unsigned int, boolean));
+static boolean ieee_float_type PARAMS ((PTR, unsigned int));
+static boolean ieee_complex_type PARAMS ((PTR, unsigned int));
+static boolean ieee_bool_type PARAMS ((PTR, unsigned int));
+static boolean ieee_enum_type
+ PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
+static boolean ieee_pointer_type PARAMS ((PTR));
+static boolean ieee_function_type PARAMS ((PTR, int, boolean));
+static boolean ieee_reference_type PARAMS ((PTR));
+static boolean ieee_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+static boolean ieee_array_type
+ PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean));
+static boolean ieee_set_type PARAMS ((PTR, boolean));
+static boolean ieee_offset_type PARAMS ((PTR));
+static boolean ieee_method_type PARAMS ((PTR, boolean, int, boolean));
+static boolean ieee_const_type PARAMS ((PTR));
+static boolean ieee_volatile_type PARAMS ((PTR));
+static boolean ieee_start_struct_type
+ PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
+static boolean ieee_struct_field
+ PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static boolean ieee_end_struct_type PARAMS ((PTR));
+static boolean ieee_start_class_type
+ PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
+ boolean));
+static boolean ieee_class_static_member
+ PARAMS ((PTR, const char *, const char *, enum debug_visibility));
+static boolean ieee_class_baseclass
+ PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility));
+static boolean ieee_class_start_method PARAMS ((PTR, const char *));
+static boolean ieee_class_method_variant
+ PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean,
+ bfd_vma, boolean));
+static boolean ieee_class_static_method_variant
+ PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean));
+static boolean ieee_class_end_method PARAMS ((PTR));
+static boolean ieee_end_class_type PARAMS ((PTR));
+static boolean ieee_typedef_type PARAMS ((PTR, const char *));
+static boolean ieee_tag_type
+ PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
+static boolean ieee_typdef PARAMS ((PTR, const char *));
+static boolean ieee_tag PARAMS ((PTR, const char *));
+static boolean ieee_int_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean ieee_float_constant PARAMS ((PTR, const char *, double));
+static boolean ieee_typed_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean ieee_variable
+ PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
+static boolean ieee_start_function PARAMS ((PTR, const char *, boolean));
+static boolean ieee_function_parameter
+ PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
+static boolean ieee_start_block PARAMS ((PTR, bfd_vma));
+static boolean ieee_end_block PARAMS ((PTR, bfd_vma));
+static boolean ieee_end_function PARAMS ((PTR));
+static boolean ieee_lineno
+ PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+
+static const struct debug_write_fns ieee_fns =
+{
+ ieee_start_compilation_unit,
+ ieee_start_source,
+ ieee_empty_type,
+ ieee_void_type,
+ ieee_int_type,
+ ieee_float_type,
+ ieee_complex_type,
+ ieee_bool_type,
+ ieee_enum_type,
+ ieee_pointer_type,
+ ieee_function_type,
+ ieee_reference_type,
+ ieee_range_type,
+ ieee_array_type,
+ ieee_set_type,
+ ieee_offset_type,
+ ieee_method_type,
+ ieee_const_type,
+ ieee_volatile_type,
+ ieee_start_struct_type,
+ ieee_struct_field,
+ ieee_end_struct_type,
+ ieee_start_class_type,
+ ieee_class_static_member,
+ ieee_class_baseclass,
+ ieee_class_start_method,
+ ieee_class_method_variant,
+ ieee_class_static_method_variant,
+ ieee_class_end_method,
+ ieee_end_class_type,
+ ieee_typedef_type,
+ ieee_tag_type,
+ ieee_typdef,
+ ieee_tag,
+ ieee_int_constant,
+ ieee_float_constant,
+ ieee_typed_constant,
+ ieee_variable,
+ ieee_start_function,
+ ieee_function_parameter,
+ ieee_start_block,
+ ieee_end_block,
+ ieee_end_function,
+ ieee_lineno
+};
+
+/* Initialize a buffer to be empty. */
+
+/*ARGSUSED*/
+static boolean
+ieee_init_buffer (info, buflist)
+ struct ieee_handle *info;
+ struct ieee_buflist *buflist;
+{
+ buflist->head = NULL;
+ buflist->tail = NULL;
+ return true;
+}
+
+/* See whether a buffer list has any data. */
+
+#define ieee_buffer_emptyp(buflist) ((buflist)->head == NULL)
+
+/* Change the current buffer to a specified buffer chain. */
+
+static boolean
+ieee_change_buffer (info, buflist)
+ struct ieee_handle *info;
+ struct ieee_buflist *buflist;
+{
+ if (buflist->head == NULL)
+ {
+ struct ieee_buf *buf;
+
+ buf = (struct ieee_buf *) xmalloc (sizeof *buf);
+ buf->next = NULL;
+ buf->c = 0;
+ buflist->head = buf;
+ buflist->tail = buf;
+ }
+
+ info->current = buflist;
+ info->curbuf = buflist->tail;
+
+ return true;
+}
+
+/* Append a buffer chain. */
+
+/*ARGSUSED*/
+static boolean
+ieee_append_buffer (info, mainbuf, newbuf)
+ struct ieee_handle *info;
+ struct ieee_buflist *mainbuf;
+ struct ieee_buflist *newbuf;
+{
+ if (newbuf->head != NULL)
+ {
+ if (mainbuf->head == NULL)
+ mainbuf->head = newbuf->head;
+ else
+ mainbuf->tail->next = newbuf->head;
+ mainbuf->tail = newbuf->tail;
+ }
+ return true;
+}
+
+/* Write a byte into the buffer. We use a macro for speed and a
+ function for the complex cases. */
+
+#define ieee_write_byte(info, b) \
+ ((info)->curbuf->c < IEEE_BUFSIZE \
+ ? ((info)->curbuf->buf[(info)->curbuf->c++] = (b), true) \
+ : ieee_real_write_byte ((info), (b)))
+
+static boolean
+ieee_real_write_byte (info, b)
+ struct ieee_handle *info;
+ int b;
+{
+ if (info->curbuf->c >= IEEE_BUFSIZE)
+ {
+ struct ieee_buf *n;
+
+ n = (struct ieee_buf *) xmalloc (sizeof *n);
+ n->next = NULL;
+ n->c = 0;
+ if (info->current->head == NULL)
+ info->current->head = n;
+ else
+ info->current->tail->next = n;
+ info->current->tail = n;
+ info->curbuf = n;
+ }
+
+ info->curbuf->buf[info->curbuf->c] = b;
+ ++info->curbuf->c;
+
+ return true;
+}
+
+/* Write out two bytes. */
+
+static boolean
+ieee_write_2bytes (info, i)
+ struct ieee_handle *info;
+ int i;
+{
+ return (ieee_write_byte (info, i >> 8)
+ && ieee_write_byte (info, i & 0xff));
+}
+
+/* Write out an integer. */
+
+static boolean
+ieee_write_number (info, v)
+ struct ieee_handle *info;
+ bfd_vma v;
+{
+ bfd_vma t;
+ bfd_byte ab[20];
+ bfd_byte *p;
+ unsigned int c;
+
+ if (v <= (bfd_vma) ieee_number_end_enum)
+ return ieee_write_byte (info, (int) v);
+
+ t = v;
+ p = ab + sizeof ab;
+ while (t != 0)
+ {
+ *--p = t & 0xff;
+ t >>= 8;
+ }
+ c = (ab + 20) - p;
+
+ if (c > (unsigned int) (ieee_number_repeat_end_enum
+ - ieee_number_repeat_start_enum))
+ {
+ fprintf (stderr, "IEEE numeric overflow: 0x");
+ fprintf_vma (stderr, v);
+ fprintf (stderr, "\n");
+ return false;
+ }
+
+ if (! ieee_write_byte (info, (int) ieee_number_repeat_start_enum + c))
+ return false;
+ for (; c > 0; --c, ++p)
+ {
+ if (! ieee_write_byte (info, *p))
+ return false;
+ }
+
+ return true;
+}
+
+/* Write out a string. */
+
+static boolean
+ieee_write_id (info, s)
+ struct ieee_handle *info;
+ const char *s;
+{
+ unsigned int len;
+
+ len = strlen (s);
+ if (len <= 0x7f)
+ {
+ if (! ieee_write_byte (info, len))
+ return false;
+ }
+ else if (len <= 0xff)
+ {
+ if (! ieee_write_byte (info, (int) ieee_extension_length_1_enum)
+ || ! ieee_write_byte (info, len))
+ return false;
+ }
+ else if (len <= 0xffff)
+ {
+ if (! ieee_write_byte (info, (int) ieee_extension_length_2_enum)
+ || ! ieee_write_2bytes (info, len))
+ return false;
+ }
+ else
+ {
+ fprintf (stderr, "IEEE string length overflow: %u\n", len);
+ return false;
+ }
+
+ for (; *s != '\0'; s++)
+ if (! ieee_write_byte (info, *s))
+ return false;
+
+ return true;
+}
+
+/* Write out an ASN record. */
+
+static boolean
+ieee_write_asn (info, indx, val)
+ struct ieee_handle *info;
+ unsigned int indx;
+ bfd_vma val;
+{
+ return (ieee_write_2bytes (info, (int) ieee_asn_record_enum)
+ && ieee_write_number (info, indx)
+ && ieee_write_number (info, val));
+}
+
+/* Write out an ATN65 record. */
+
+static boolean
+ieee_write_atn65 (info, indx, s)
+ struct ieee_handle *info;
+ unsigned int indx;
+ const char *s;
+{
+ return (ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ && ieee_write_number (info, indx)
+ && ieee_write_number (info, 0)
+ && ieee_write_number (info, 65)
+ && ieee_write_id (info, s));
+}
+
+/* Push a type index onto the type stack. */
+
+static boolean
+ieee_push_type (info, indx, size, unsignedp, localp)
+ struct ieee_handle *info;
+ unsigned int indx;
+ unsigned int size;
+ boolean unsignedp;
+ boolean localp;
+{
+ struct ieee_type_stack *ts;
+
+ ts = (struct ieee_type_stack *) xmalloc (sizeof *ts);
+ memset (ts, 0, sizeof *ts);
+
+ ts->type.indx = indx;
+ ts->type.size = size;
+ ts->type.unsignedp = unsignedp;
+ ts->type.localp = localp;
+
+ ts->next = info->type_stack;
+ info->type_stack = ts;
+
+ return true;
+}
+
+/* Pop a type index off the type stack. */
+
+static unsigned int
+ieee_pop_type (info)
+ struct ieee_handle *info;
+{
+ return ieee_pop_type_used (info, true);
+}
+
+/* Pop an unused type index off the type stack. */
+
+static void
+ieee_pop_unused_type (info)
+ struct ieee_handle *info;
+{
+ (void) ieee_pop_type_used (info, false);
+}
+
+/* Pop a used or unused type index off the type stack. */
+
+static unsigned int
+ieee_pop_type_used (info, used)
+ struct ieee_handle *info;
+ boolean used;
+{
+ struct ieee_type_stack *ts;
+ unsigned int ret;
+
+ ts = info->type_stack;
+ assert (ts != NULL);
+
+ /* If this is a function type, and we need it, we need to append the
+ actual definition to the typedef block now. */
+ if (used && ! ieee_buffer_emptyp (&ts->type.fndef))
+ {
+ struct ieee_buflist *buflist;
+
+ if (ts->type.localp)
+ {
+ /* Make sure we have started the types block. */
+ if (ieee_buffer_emptyp (&info->types))
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+ }
+ buflist = &info->types;
+ }
+ else
+ {
+ /* Make sure we started the global type block. */
+ if (ieee_buffer_emptyp (&info->global_types))
+ {
+ if (! ieee_change_buffer (info, &info->global_types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 2)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, ""))
+ return false;
+ }
+ buflist = &info->global_types;
+ }
+
+ if (! ieee_append_buffer (info, buflist, &ts->type.fndef))
+ return false;
+ }
+
+ ret = ts->type.indx;
+ info->type_stack = ts->next;
+ free (ts);
+ return ret;
+}
+
+/* Add a range of bytes included in the current compilation unit. */
+
+static boolean
+ieee_add_range (info, global, low, high)
+ struct ieee_handle *info;
+ boolean global;
+ bfd_vma low;
+ bfd_vma high;
+{
+ struct ieee_range **plist, *r, **pr;
+
+ if (low == (bfd_vma) -1 || high == (bfd_vma) -1 || low == high)
+ return true;
+
+ if (global)
+ plist = &info->global_ranges;
+ else
+ plist = &info->ranges;
+
+ for (r = *plist; r != NULL; r = r->next)
+ {
+ if (high >= r->low && low <= r->high)
+ {
+ /* The new range overlaps r. */
+ if (low < r->low)
+ r->low = low;
+ if (high > r->high)
+ r->high = high;
+ pr = &r->next;
+ while (*pr != NULL && (*pr)->low <= r->high)
+ {
+ struct ieee_range *n;
+
+ if ((*pr)->high > r->high)
+ r->high = (*pr)->high;
+ n = (*pr)->next;
+ free (*pr);
+ *pr = n;
+ }
+ return true;
+ }
+ }
+
+ r = (struct ieee_range *) xmalloc (sizeof *r);
+ memset (r, 0, sizeof *r);
+
+ r->low = low;
+ r->high = high;
+
+ /* Store the ranges sorted by address. */
+ for (pr = plist; *pr != NULL; pr = &(*pr)->next)
+ if ((*pr)->low > high)
+ break;
+ r->next = *pr;
+ *pr = r;
+
+ return true;
+}
+
+/* Start a new range for which we only have the low address. */
+
+static boolean
+ieee_start_range (info, low)
+ struct ieee_handle *info;
+ bfd_vma low;
+{
+ struct ieee_range *r;
+
+ r = (struct ieee_range *) xmalloc (sizeof *r);
+ memset (r, 0, sizeof *r);
+ r->low = low;
+ r->next = info->pending_ranges;
+ info->pending_ranges = r;
+ return true;
+}
+
+/* Finish a range started by ieee_start_range. */
+
+static boolean
+ieee_end_range (info, high)
+ struct ieee_handle *info;
+ bfd_vma high;
+{
+ struct ieee_range *r;
+ bfd_vma low;
+
+ assert (info->pending_ranges != NULL);
+ r = info->pending_ranges;
+ low = r->low;
+ info->pending_ranges = r->next;
+ free (r);
+ return ieee_add_range (info, false, low, high);
+}
+
+/* Start defining a type. */
+
+static boolean
+ieee_define_type (info, size, unsignedp, localp)
+ struct ieee_handle *info;
+ unsigned int size;
+ boolean unsignedp;
+ boolean localp;
+{
+ return ieee_define_named_type (info, (const char *) NULL,
+ (unsigned int) -1, size, unsignedp,
+ localp, (struct ieee_buflist *) NULL);
+}
+
+/* Start defining a named type. */
+
+static boolean
+ieee_define_named_type (info, name, indx, size, unsignedp, localp, buflist)
+ struct ieee_handle *info;
+ const char *name;
+ unsigned int indx;
+ unsigned int size;
+ boolean unsignedp;
+ boolean localp;
+ struct ieee_buflist *buflist;
+{
+ unsigned int type_indx;
+ unsigned int name_indx;
+
+ if (indx != (unsigned int) -1)
+ type_indx = indx;
+ else
+ {
+ type_indx = info->type_indx;
+ ++info->type_indx;
+ }
+
+ name_indx = info->name_indx;
+ ++info->name_indx;
+
+ if (name == NULL)
+ name = "";
+
+ /* If we were given a buffer, use it; otherwise, use either the
+ local or the global type information, and make sure that the type
+ block is started. */
+ if (buflist != NULL)
+ {
+ if (! ieee_change_buffer (info, buflist))
+ return false;
+ }
+ else if (localp)
+ {
+ if (! ieee_buffer_emptyp (&info->types))
+ {
+ if (! ieee_change_buffer (info, &info->types))
+ return false;
+ }
+ else
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+ }
+ }
+ else
+ {
+ if (! ieee_buffer_emptyp (&info->global_types))
+ {
+ if (! ieee_change_buffer (info, &info->global_types))
+ return false;
+ }
+ else
+ {
+ if (! ieee_change_buffer (info, &info->global_types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 2)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, ""))
+ return false;
+ }
+ }
+
+ /* Push the new type on the type stack, write out an NN record, and
+ write out the start of a TY record. The caller will then finish
+ the TY record. */
+ if (! ieee_push_type (info, type_indx, size, unsignedp, localp))
+ return false;
+
+ return (ieee_write_byte (info, (int) ieee_nn_record)
+ && ieee_write_number (info, name_indx)
+ && ieee_write_id (info, name)
+ && ieee_write_byte (info, (int) ieee_ty_record_enum)
+ && ieee_write_number (info, type_indx)
+ && ieee_write_byte (info, 0xce)
+ && ieee_write_number (info, name_indx));
+}
+
+/* Get an entry to the list of modified versions of a type. */
+
+static struct ieee_modified_type *
+ieee_get_modified_info (info, indx)
+ struct ieee_handle *info;
+ unsigned int indx;
+{
+ if (indx >= info->modified_alloc)
+ {
+ unsigned int nalloc;
+
+ nalloc = info->modified_alloc;
+ if (nalloc == 0)
+ nalloc = 16;
+ while (indx >= nalloc)
+ nalloc *= 2;
+ info->modified = ((struct ieee_modified_type *)
+ xrealloc (info->modified,
+ nalloc * sizeof *info->modified));
+ memset (info->modified + info->modified_alloc, 0,
+ (nalloc - info->modified_alloc) * sizeof *info->modified);
+ info->modified_alloc = nalloc;
+ }
+
+ return info->modified + indx;
+}
+
+/* Routines for the hash table mapping names to types. */
+
+/* Initialize an entry in the hash table. */
+
+static struct bfd_hash_entry *
+ieee_name_type_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct ieee_name_type_hash_entry *ret =
+ (struct ieee_name_type_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == NULL)
+ ret = ((struct ieee_name_type_hash_entry *)
+ bfd_hash_allocate (table, sizeof *ret));
+ if (ret == NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct ieee_name_type_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+ if (ret)
+ {
+ /* Set local fields. */
+ ret->types = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Look up an entry in the hash table. */
+
+#define ieee_name_type_hash_lookup(table, string, create, copy) \
+ ((struct ieee_name_type_hash_entry *) \
+ bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
+
+/* Traverse the hash table. */
+
+#define ieee_name_type_hash_traverse(table, func, info) \
+ (bfd_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* The general routine to write out IEEE debugging information. */
+
+boolean
+write_ieee_debugging_info (abfd, dhandle)
+ bfd *abfd;
+ PTR dhandle;
+{
+ struct ieee_handle info;
+ asection *s;
+ const char *err;
+ struct ieee_buf *b;
+
+ memset (&info, 0, sizeof info);
+ info.abfd = abfd;
+ info.type_indx = 256;
+ info.name_indx = 32;
+
+ if (! bfd_hash_table_init (&info.typedefs.root, ieee_name_type_newfunc)
+ || ! bfd_hash_table_init (&info.tags.root, ieee_name_type_newfunc))
+ return false;
+
+ if (! ieee_init_buffer (&info, &info.global_types)
+ || ! ieee_init_buffer (&info, &info.data)
+ || ! ieee_init_buffer (&info, &info.types)
+ || ! ieee_init_buffer (&info, &info.vars)
+ || ! ieee_init_buffer (&info, &info.cxx)
+ || ! ieee_init_buffer (&info, &info.linenos)
+ || ! ieee_init_buffer (&info, &info.fntype)
+ || ! ieee_init_buffer (&info, &info.fnargs))
+ return false;
+
+ if (! debug_write (dhandle, &ieee_fns, (PTR) &info))
+ return false;
+
+ if (info.filename != NULL)
+ {
+ if (! ieee_finish_compilation_unit (&info))
+ return false;
+ }
+
+ /* Put any undefined tags in the global typedef information. */
+ info.error = false;
+ ieee_name_type_hash_traverse (&info.tags,
+ ieee_write_undefined_tag,
+ (PTR) &info);
+ if (info.error)
+ return false;
+
+ /* Prepend the global typedef information to the other data. */
+ if (! ieee_buffer_emptyp (&info.global_types))
+ {
+ if (! ieee_change_buffer (&info, &info.global_types)
+ || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
+ return false;
+
+ if (! ieee_append_buffer (&info, &info.global_types, &info.data))
+ return false;
+ info.data = info.global_types;
+ }
+
+ /* Make sure that we have declare BB11 blocks for each range in the
+ file. They are added to info->vars. */
+ info.error = false;
+ if (! ieee_init_buffer (&info, &info.vars))
+ return false;
+ bfd_map_over_sections (abfd, ieee_add_bb11_blocks, (PTR) &info);
+ if (info.error)
+ return false;
+ if (! ieee_buffer_emptyp (&info.vars))
+ {
+ if (! ieee_change_buffer (&info, &info.vars)
+ || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
+ return false;
+
+ if (! ieee_append_buffer (&info, &info.data, &info.vars))
+ return false;
+ }
+
+ /* Now all the data is in info.data. Write it out to the BFD. We
+ normally would need to worry about whether all the other sections
+ are set up yet, but the IEEE backend will handle this particular
+ case correctly regardless. */
+ if (ieee_buffer_emptyp (&info.data))
+ {
+ /* There is no debugging information. */
+ return true;
+ }
+ err = NULL;
+ s = bfd_make_section (abfd, ".debug");
+ if (s == NULL)
+ err = "bfd_make_section";
+ if (err == NULL)
+ {
+ if (! bfd_set_section_flags (abfd, s, SEC_DEBUGGING | SEC_HAS_CONTENTS))
+ err = "bfd_set_section_flags";
+ }
+ if (err == NULL)
+ {
+ bfd_size_type size;
+
+ size = 0;
+ for (b = info.data.head; b != NULL; b = b->next)
+ size += b->c;
+ if (! bfd_set_section_size (abfd, s, size))
+ err = "bfd_set_section_size";
+ }
+ if (err == NULL)
+ {
+ file_ptr offset;
+
+ offset = 0;
+ for (b = info.data.head; b != NULL; b = b->next)
+ {
+ if (! bfd_set_section_contents (abfd, s, b->buf, offset, b->c))
+ {
+ err = "bfd_set_section_contents";
+ break;
+ }
+ offset += b->c;
+ }
+ }
+
+ if (err != NULL)
+ {
+ fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), err,
+ bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+
+ bfd_hash_table_free (&info.typedefs.root);
+ bfd_hash_table_free (&info.tags.root);
+
+ return true;
+}
+
+/* Write out information for an undefined tag. This is called via
+ ieee_name_type_hash_traverse. */
+
+static boolean
+ieee_write_undefined_tag (h, p)
+ struct ieee_name_type_hash_entry *h;
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_name_type *nt;
+
+ for (nt = h->types; nt != NULL; nt = nt->next)
+ {
+ unsigned int name_indx;
+ char code;
+
+ if (nt->kind == DEBUG_KIND_ILLEGAL)
+ continue;
+
+ if (ieee_buffer_emptyp (&info->global_types))
+ {
+ if (! ieee_change_buffer (info, &info->global_types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 2)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, ""))
+ {
+ info->error = true;
+ return false;
+ }
+ }
+ else
+ {
+ if (! ieee_change_buffer (info, &info->global_types))
+ {
+ info->error = true;
+ return false;
+ }
+ }
+
+ name_indx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, name_indx)
+ || ! ieee_write_id (info, nt->type.name)
+ || ! ieee_write_byte (info, (int) ieee_ty_record_enum)
+ || ! ieee_write_number (info, nt->type.indx)
+ || ! ieee_write_byte (info, 0xce)
+ || ! ieee_write_number (info, name_indx))
+ {
+ info->error = true;
+ return false;
+ }
+
+ switch (nt->kind)
+ {
+ default:
+ abort ();
+ info->error = true;
+ return false;
+ case DEBUG_KIND_STRUCT:
+ case DEBUG_KIND_CLASS:
+ code = 'S';
+ break;
+ case DEBUG_KIND_UNION:
+ case DEBUG_KIND_UNION_CLASS:
+ code = 'U';
+ break;
+ case DEBUG_KIND_ENUM:
+ code = 'E';
+ break;
+ }
+ if (! ieee_write_number (info, code)
+ || ! ieee_write_number (info, 0))
+ {
+ info->error = true;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Start writing out information for a compilation unit. */
+
+static boolean
+ieee_start_compilation_unit (p, filename)
+ PTR p;
+ const char *filename;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ const char *modname;
+ char *c, *s;
+ unsigned int nindx;
+
+ if (info->filename != NULL)
+ {
+ if (! ieee_finish_compilation_unit (info))
+ return false;
+ }
+
+ info->filename = filename;
+ modname = strrchr (filename, '/');
+ if (modname != NULL)
+ ++modname;
+ else
+ {
+ modname = strrchr (filename, '\\');
+ if (modname != NULL)
+ ++modname;
+ else
+ modname = filename;
+ }
+ c = xstrdup (modname);
+ s = strrchr (c, '.');
+ if (s != NULL)
+ *s = '\0';
+ info->modname = c;
+
+ if (! ieee_init_buffer (info, &info->types)
+ || ! ieee_init_buffer (info, &info->vars)
+ || ! ieee_init_buffer (info, &info->cxx)
+ || ! ieee_init_buffer (info, &info->linenos))
+ return false;
+ info->ranges = NULL;
+
+ /* Always include a BB1 and a BB3 block. That is what the output of
+ the MRI linker seems to look like. */
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 3)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+
+ return true;
+}
+
+/* Finish up a compilation unit. */
+
+static boolean
+ieee_finish_compilation_unit (info)
+ struct ieee_handle *info;
+{
+ struct ieee_range *r;
+
+ if (! ieee_buffer_emptyp (&info->types))
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ }
+
+ if (! ieee_buffer_emptyp (&info->cxx))
+ {
+ /* Append any C++ information to the global function and
+ variable information. */
+ assert (! ieee_buffer_emptyp (&info->vars));
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+
+ /* We put the pmisc records in a dummy procedure, just as the
+ MRI compiler does. */
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 6)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "__XRYCPP")
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, info->highaddr - 1)
+ || ! ieee_append_buffer (info, &info->vars, &info->cxx)
+ || ! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+ || ! ieee_write_number (info, info->highaddr - 1))
+ return false;
+ }
+
+ if (! ieee_buffer_emptyp (&info->vars))
+ {
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ }
+
+ if (info->pending_lineno_filename != NULL)
+ {
+ /* Force out the pending line number. */
+ if (! ieee_lineno ((PTR) info, (const char *) NULL, 0, (bfd_vma) -1))
+ return false;
+ }
+ if (! ieee_buffer_emptyp (&info->linenos))
+ {
+ if (! ieee_change_buffer (info, &info->linenos)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ if (strcmp (info->filename, info->lineno_filename) != 0)
+ {
+ /* We were not in the main file. We just closed the
+ included line number block, and now we must close the
+ main line number block. */
+ if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ }
+ }
+
+ if (! ieee_append_buffer (info, &info->data, &info->types)
+ || ! ieee_append_buffer (info, &info->data, &info->vars)
+ || ! ieee_append_buffer (info, &info->data, &info->linenos))
+ return false;
+
+ /* Build BB10/BB11 blocks based on the ranges we recorded. */
+ if (! ieee_change_buffer (info, &info->data))
+ return false;
+
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 10)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "GNU objcopy"))
+ return false;
+
+ for (r = info->ranges; r != NULL; r = r->next)
+ {
+ bfd_vma low, high;
+ asection *s;
+ int kind;
+
+ low = r->low;
+ high = r->high;
+
+ /* Find the section corresponding to this range. */
+ for (s = info->abfd->sections; s != NULL; s = s->next)
+ {
+ if (bfd_get_section_vma (info->abfd, s) <= low
+ && high <= (bfd_get_section_vma (info->abfd, s)
+ + bfd_section_size (info->abfd, s)))
+ break;
+ }
+
+ if (s == NULL)
+ {
+ /* Just ignore this range. */
+ continue;
+ }
+
+ /* Coalesce ranges if it seems reasonable. */
+ while (r->next != NULL
+ && high + 64 >= r->next->low
+ && (r->next->high
+ <= (bfd_get_section_vma (info->abfd, s)
+ + bfd_section_size (info->abfd, s))))
+ {
+ r = r->next;
+ high = r->high;
+ }
+
+ if ((s->flags & SEC_CODE) != 0)
+ kind = 1;
+ else if ((s->flags & SEC_READONLY) != 0)
+ kind = 3;
+ else
+ kind = 2;
+
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 11)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_number (info, kind)
+ || ! ieee_write_number (info, s->index + IEEE_SECTION_NUMBER_BASE)
+ || ! ieee_write_number (info, low)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+ || ! ieee_write_number (info, high - low))
+ return false;
+
+ /* Add this range to the list of global ranges. */
+ if (! ieee_add_range (info, true, low, high))
+ return false;
+ }
+
+ if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+
+ return true;
+}
+
+/* Add BB11 blocks describing each range that we have not already
+ described. */
+
+static void
+ieee_add_bb11_blocks (abfd, sec, data)
+ bfd *abfd;
+ asection *sec;
+ PTR data;
+{
+ struct ieee_handle *info = (struct ieee_handle *) data;
+ bfd_vma low, high;
+ struct ieee_range *r;
+
+ low = bfd_get_section_vma (abfd, sec);
+ high = low + bfd_section_size (abfd, sec);
+
+ /* Find the first range at or after this section. The ranges are
+ sorted by address. */
+ for (r = info->global_ranges; r != NULL; r = r->next)
+ if (r->high > low)
+ break;
+
+ while (low < high)
+ {
+ if (r == NULL || r->low >= high)
+ {
+ if (! ieee_add_bb11 (info, sec, low, high))
+ info->error = true;
+ return;
+ }
+
+ if (low < r->low)
+ {
+ if (! ieee_add_bb11 (info, sec, low, r->low))
+ {
+ info->error = true;
+ return;
+ }
+ }
+ low = r->high;
+
+ r = r->next;
+ }
+}
+
+/* Add a single BB11 block for a range. We add it to info->vars. */
+
+static boolean
+ieee_add_bb11 (info, sec, low, high)
+ struct ieee_handle *info;
+ asection *sec;
+ bfd_vma low;
+ bfd_vma high;
+{
+ int kind;
+
+ if (! ieee_buffer_emptyp (&info->vars))
+ {
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+ }
+ else
+ {
+ const char *filename, *modname;
+ char *c, *s;
+
+ /* Start the enclosing BB10 block. */
+ filename = bfd_get_filename (info->abfd);
+ modname = strrchr (filename, '/');
+ if (modname != NULL)
+ ++modname;
+ else
+ {
+ modname = strrchr (filename, '\\');
+ if (modname != NULL)
+ ++modname;
+ else
+ modname = filename;
+ }
+ c = xstrdup (modname);
+ s = strrchr (c, '.');
+ if (s != NULL)
+ *s = '\0';
+
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 10)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, c)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "GNU objcopy"))
+ return false;
+
+ free (c);
+ }
+
+ if ((sec->flags & SEC_CODE) != 0)
+ kind = 1;
+ else if ((sec->flags & SEC_READONLY) != 0)
+ kind = 3;
+ else
+ kind = 2;
+
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 11)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_number (info, kind)
+ || ! ieee_write_number (info, sec->index + IEEE_SECTION_NUMBER_BASE)
+ || ! ieee_write_number (info, low)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+ || ! ieee_write_number (info, high - low))
+ return false;
+
+ return true;
+}
+
+/* Start recording information from a particular source file. This is
+ used to record which file defined which types, variables, etc. It
+ is not used for line numbers, since the lineno entry point passes
+ down the file name anyhow. IEEE debugging information doesn't seem
+ to store this information anywhere. */
+
+/*ARGSUSED*/
+static boolean
+ieee_start_source (p, filename)
+ PTR p;
+ const char *filename;
+{
+ return true;
+}
+
+/* Make an empty type. */
+
+static boolean
+ieee_empty_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ return ieee_push_type (info, (int) builtin_unknown, 0, false, false);
+}
+
+/* Make a void type. */
+
+static boolean
+ieee_void_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ return ieee_push_type (info, (int) builtin_void, 0, false, false);
+}
+
+/* Make an integer type. */
+
+static boolean
+ieee_int_type (p, size, unsignedp)
+ PTR p;
+ unsigned int size;
+ boolean unsignedp;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int indx;
+
+ switch (size)
+ {
+ case 1:
+ indx = (int) builtin_signed_char;
+ break;
+ case 2:
+ indx = (int) builtin_signed_short_int;
+ break;
+ case 4:
+ indx = (int) builtin_signed_long;
+ break;
+ case 8:
+ indx = (int) builtin_signed_long_long;
+ break;
+ default:
+ fprintf (stderr, "IEEE unsupported integer type size %u\n", size);
+ return false;
+ }
+
+ if (unsignedp)
+ ++indx;
+
+ return ieee_push_type (info, indx, size, unsignedp, false);
+}
+
+/* Make a floating point type. */
+
+static boolean
+ieee_float_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int indx;
+
+ switch (size)
+ {
+ case 4:
+ indx = (int) builtin_float;
+ break;
+ case 8:
+ indx = (int) builtin_double;
+ break;
+ case 12:
+ /* FIXME: This size really depends upon the processor. */
+ indx = (int) builtin_long_double;
+ break;
+ case 16:
+ indx = (int) builtin_long_long_double;
+ break;
+ default:
+ fprintf (stderr, "IEEE unsupported float type size %u\n", size);
+ return false;
+ }
+
+ return ieee_push_type (info, indx, size, false, false);
+}
+
+/* Make a complex type. */
+
+static boolean
+ieee_complex_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ char code;
+
+ switch (size)
+ {
+ case 4:
+ if (info->complex_float_index != 0)
+ return ieee_push_type (info, info->complex_float_index, size * 2,
+ false, false);
+ code = 'c';
+ break;
+ case 12:
+ case 16:
+ /* These cases can be output by gcc -gstabs. Outputting the
+ wrong type is better than crashing. */
+ case 8:
+ if (info->complex_double_index != 0)
+ return ieee_push_type (info, info->complex_double_index, size * 2,
+ false, false);
+ code = 'd';
+ break;
+ default:
+ fprintf (stderr, "IEEE unsupported complex type size %u\n", size);
+ return false;
+ }
+
+ /* FIXME: I don't know what the string is for. */
+ if (! ieee_define_type (info, size * 2, false, false)
+ || ! ieee_write_number (info, code)
+ || ! ieee_write_id (info, ""))
+ return false;
+
+ if (size == 4)
+ info->complex_float_index = info->type_stack->type.indx;
+ else
+ info->complex_double_index = info->type_stack->type.indx;
+
+ return true;
+}
+
+/* Make a boolean type. IEEE doesn't support these, so we just make
+ an integer type instead. */
+
+static boolean
+ieee_bool_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ return ieee_int_type (p, size, true);
+}
+
+/* Make an enumeration. */
+
+static boolean
+ieee_enum_type (p, tag, names, vals)
+ PTR p;
+ const char *tag;
+ const char **names;
+ bfd_signed_vma *vals;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_defined_enum *e;
+ boolean localp, simple;
+ int i;
+
+ localp = false;
+ for (e = info->enums; e != NULL; e = e->next)
+ {
+ if (tag == NULL)
+ {
+ if (e->tag != NULL)
+ continue;
+ }
+ else
+ {
+ if (e->tag == NULL
+ || tag[0] != e->tag[0]
+ || strcmp (tag, e->tag) != 0)
+ continue;
+ }
+
+ if (names != NULL && e->names != NULL)
+ {
+ for (i = 0; names[i] != NULL && e->names[i] != NULL; i++)
+ {
+ if (names[i][0] != e->names[i][0]
+ || vals[i] != e->vals[i]
+ || strcmp (names[i], e->names[i]) != 0)
+ break;
+ }
+ }
+
+ if ((names == NULL && e->names == NULL)
+ || (names[i] == NULL && e->names[i] == NULL))
+ {
+ /* We've seen this enum before. */
+ return ieee_push_type (info, e->indx, 0, true, false);
+ }
+
+ if (tag != NULL)
+ {
+ /* We've already seen an enum of the same name, so we must make
+ sure to output this one locally. */
+ localp = true;
+ break;
+ }
+ }
+
+ /* If this is a simple enumeration, in which the values start at 0
+ and always increment by 1, we can use type E. Otherwise we must
+ use type N. */
+
+ simple = true;
+ if (names != NULL)
+ {
+ for (i = 0; names[i] != NULL; i++)
+ {
+ if (vals[i] != i)
+ {
+ simple = false;
+ break;
+ }
+ }
+ }
+
+ if (! ieee_define_named_type (info, tag, (unsigned int) -1, 0,
+ true, localp, (struct ieee_buflist *) NULL)
+ || ! ieee_write_number (info, simple ? 'E' : 'N'))
+ return false;
+ if (simple)
+ {
+ /* FIXME: This is supposed to be the enumeration size, but we
+ don't store that. */
+ if (! ieee_write_number (info, 4))
+ return false;
+ }
+ if (names != NULL)
+ {
+ for (i = 0; names[i] != NULL; i++)
+ {
+ if (! ieee_write_id (info, names[i]))
+ return false;
+ if (! simple)
+ {
+ if (! ieee_write_number (info, vals[i]))
+ return false;
+ }
+ }
+ }
+
+ if (! localp)
+ {
+ e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
+ memset (e, 0, sizeof *e);
+
+ e->indx = info->type_stack->type.indx;
+ e->tag = tag;
+ e->names = names;
+ e->vals = vals;
+
+ e->next = info->enums;
+ info->enums = e;
+ }
+
+ return true;
+}
+
+/* Make a pointer type. */
+
+static boolean
+ieee_pointer_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp;
+ unsigned int indx;
+ struct ieee_modified_type *m = NULL;
+
+ localp = info->type_stack->type.localp;
+ indx = ieee_pop_type (info);
+
+ /* A pointer to a simple builtin type can be obtained by adding 32.
+ FIXME: Will this be a short pointer, and will that matter? */
+ if (indx < 32)
+ return ieee_push_type (info, indx + 32, 0, true, false);
+
+ if (! localp)
+ {
+ m = ieee_get_modified_info (p, indx);
+ if (m == NULL)
+ return false;
+
+ /* FIXME: The size should depend upon the architecture. */
+ if (m->pointer > 0)
+ return ieee_push_type (info, m->pointer, 4, true, false);
+ }
+
+ if (! ieee_define_type (info, 4, true, localp)
+ || ! ieee_write_number (info, 'P')
+ || ! ieee_write_number (info, indx))
+ return false;
+
+ if (! localp)
+ m->pointer = info->type_stack->type.indx;
+
+ return true;
+}
+
+/* Make a function type. This will be called for a method, but we
+ don't want to actually add it to the type table in that case. We
+ handle this by defining the type in a private buffer, and only
+ adding that buffer to the typedef block if we are going to use it. */
+
+static boolean
+ieee_function_type (p, argcount, varargs)
+ PTR p;
+ int argcount;
+ boolean varargs;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp;
+ unsigned int *args = NULL;
+ int i;
+ unsigned int retindx;
+ struct ieee_buflist fndef;
+ struct ieee_modified_type *m;
+
+ localp = false;
+
+ if (argcount > 0)
+ {
+ args = (unsigned int *) xmalloc (argcount * sizeof *args);
+ for (i = argcount - 1; i >= 0; i--)
+ {
+ if (info->type_stack->type.localp)
+ localp = true;
+ args[i] = ieee_pop_type (info);
+ }
+ }
+ else if (argcount < 0)
+ varargs = false;
+
+ if (info->type_stack->type.localp)
+ localp = true;
+ retindx = ieee_pop_type (info);
+
+ m = NULL;
+ if (argcount < 0 && ! localp)
+ {
+ m = ieee_get_modified_info (p, retindx);
+ if (m == NULL)
+ return false;
+
+ if (m->function > 0)
+ return ieee_push_type (info, m->function, 0, true, false);
+ }
+
+ /* An attribute of 0x41 means that the frame and push mask are
+ unknown. */
+ if (! ieee_init_buffer (info, &fndef)
+ || ! ieee_define_named_type (info, (const char *) NULL,
+ (unsigned int) -1, 0, true, localp,
+ &fndef)
+ || ! ieee_write_number (info, 'x')
+ || ! ieee_write_number (info, 0x41)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, retindx)
+ || ! ieee_write_number (info, (bfd_vma) argcount + (varargs ? 1 : 0)))
+ return false;
+ if (argcount > 0)
+ {
+ for (i = 0; i < argcount; i++)
+ if (! ieee_write_number (info, args[i]))
+ return false;
+ free (args);
+ }
+ if (varargs)
+ {
+ /* A varargs function is represented by writing out the last
+ argument as type void *, although this makes little sense. */
+ if (! ieee_write_number (info, (bfd_vma) builtin_void + 32))
+ return false;
+ }
+
+ if (! ieee_write_number (info, 0))
+ return false;
+
+ /* We wrote the information into fndef, in case we don't need it.
+ It will be appended to info->types by ieee_pop_type. */
+ info->type_stack->type.fndef = fndef;
+
+ if (m != NULL)
+ m->function = info->type_stack->type.indx;
+
+ return true;
+}
+
+/* Make a reference type. */
+
+static boolean
+ieee_reference_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ /* IEEE appears to record a normal pointer type, and then use a
+ pmisc record to indicate that it is really a reference. */
+
+ if (! ieee_pointer_type (p))
+ return false;
+ info->type_stack->type.referencep = true;
+ return true;
+}
+
+/* Make a range type. */
+
+static boolean
+ieee_range_type (p, low, high)
+ PTR p;
+ bfd_signed_vma low;
+ bfd_signed_vma high;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int size;
+ boolean unsignedp, localp;
+
+ size = info->type_stack->type.size;
+ unsignedp = info->type_stack->type.unsignedp;
+ localp = info->type_stack->type.localp;
+ ieee_pop_unused_type (info);
+ return (ieee_define_type (info, size, unsignedp, localp)
+ && ieee_write_number (info, 'R')
+ && ieee_write_number (info, (bfd_vma) low)
+ && ieee_write_number (info, (bfd_vma) high)
+ && ieee_write_number (info, unsignedp ? 0 : 1)
+ && ieee_write_number (info, size));
+}
+
+/* Make an array type. */
+
+/*ARGSUSED*/
+static boolean
+ieee_array_type (p, low, high, stringp)
+ PTR p;
+ bfd_signed_vma low;
+ bfd_signed_vma high;
+ boolean stringp;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int eleindx;
+ boolean localp;
+ struct ieee_modified_type *m = NULL;
+ struct ieee_modified_array_type *a;
+
+ /* IEEE does not store the range, so we just ignore it. */
+ ieee_pop_unused_type (info);
+ localp = info->type_stack->type.localp;
+ eleindx = ieee_pop_type (info);
+
+ if (! localp)
+ {
+ m = ieee_get_modified_info (info, eleindx);
+ if (m == NULL)
+ return false;
+
+ for (a = m->arrays; a != NULL; a = a->next)
+ {
+ if (a->low == low && a->high == high)
+ return ieee_push_type (info, a->indx, 0, false, false);
+ }
+ }
+
+ if (! ieee_define_type (info, 0, false, localp)
+ || ! ieee_write_number (info, low == 0 ? 'Z' : 'C')
+ || ! ieee_write_number (info, eleindx))
+ return false;
+ if (low != 0)
+ {
+ if (! ieee_write_number (info, low))
+ return false;
+ }
+
+ if (! ieee_write_number (info, high + 1))
+ return false;
+
+ if (! localp)
+ {
+ a = (struct ieee_modified_array_type *) xmalloc (sizeof *a);
+ memset (a, 0, sizeof *a);
+
+ a->indx = info->type_stack->type.indx;
+ a->low = low;
+ a->high = high;
+
+ a->next = m->arrays;
+ m->arrays = a;
+ }
+
+ return true;
+}
+
+/* Make a set type. */
+
+static boolean
+ieee_set_type (p, bitstringp)
+ PTR p;
+ boolean bitstringp;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp;
+ unsigned int eleindx;
+
+ localp = info->type_stack->type.localp;
+ eleindx = ieee_pop_type (info);
+
+ /* FIXME: We don't know the size, so we just use 4. */
+
+ return (ieee_define_type (info, 0, true, localp)
+ && ieee_write_number (info, 's')
+ && ieee_write_number (info, 4)
+ && ieee_write_number (info, eleindx));
+}
+
+/* Make an offset type. */
+
+static boolean
+ieee_offset_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int targetindx, baseindx;
+
+ targetindx = ieee_pop_type (info);
+ baseindx = ieee_pop_type (info);
+
+ /* FIXME: The MRI C++ compiler does not appear to generate any
+ useful type information about an offset type. It just records a
+ pointer to member as an integer. The MRI/HP IEEE spec does
+ describe a pmisc record which can be used for a pointer to
+ member. Unfortunately, it does not describe the target type,
+ which seems pretty important. I'm going to punt this for now. */
+
+ return ieee_int_type (p, 4, true);
+}
+
+/* Make a method type. */
+
+static boolean
+ieee_method_type (p, domain, argcount, varargs)
+ PTR p;
+ boolean domain;
+ int argcount;
+ boolean varargs;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ /* FIXME: The MRI/HP IEEE spec defines a pmisc record to use for a
+ method, but the definition is incomplete. We just output an 'x'
+ type. */
+
+ if (domain)
+ ieee_pop_unused_type (info);
+
+ return ieee_function_type (p, argcount, varargs);
+}
+
+/* Make a const qualified type. */
+
+static boolean
+ieee_const_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int size;
+ boolean unsignedp, localp;
+ unsigned int indx;
+ struct ieee_modified_type *m = NULL;
+
+ size = info->type_stack->type.size;
+ unsignedp = info->type_stack->type.unsignedp;
+ localp = info->type_stack->type.localp;
+ indx = ieee_pop_type (info);
+
+ if (! localp)
+ {
+ m = ieee_get_modified_info (info, indx);
+ if (m == NULL)
+ return false;
+
+ if (m->const_qualified > 0)
+ return ieee_push_type (info, m->const_qualified, size, unsignedp,
+ false);
+ }
+
+ if (! ieee_define_type (info, size, unsignedp, localp)
+ || ! ieee_write_number (info, 'n')
+ || ! ieee_write_number (info, 1)
+ || ! ieee_write_number (info, indx))
+ return false;
+
+ if (! localp)
+ m->const_qualified = info->type_stack->type.indx;
+
+ return true;
+}
+
+/* Make a volatile qualified type. */
+
+static boolean
+ieee_volatile_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int size;
+ boolean unsignedp, localp;
+ unsigned int indx;
+ struct ieee_modified_type *m = NULL;
+
+ size = info->type_stack->type.size;
+ unsignedp = info->type_stack->type.unsignedp;
+ localp = info->type_stack->type.localp;
+ indx = ieee_pop_type (info);
+
+ if (! localp)
+ {
+ m = ieee_get_modified_info (info, indx);
+ if (m == NULL)
+ return false;
+
+ if (m->volatile_qualified > 0)
+ return ieee_push_type (info, m->volatile_qualified, size, unsignedp,
+ false);
+ }
+
+ if (! ieee_define_type (info, size, unsignedp, localp)
+ || ! ieee_write_number (info, 'n')
+ || ! ieee_write_number (info, 2)
+ || ! ieee_write_number (info, indx))
+ return false;
+
+ if (! localp)
+ m->volatile_qualified = info->type_stack->type.indx;
+
+ return true;
+}
+
+/* Convert an enum debug_visibility into a CXXFLAGS value. */
+
+static unsigned int
+ieee_vis_to_flags (visibility)
+ enum debug_visibility visibility;
+{
+ switch (visibility)
+ {
+ default:
+ abort ();
+ case DEBUG_VISIBILITY_PUBLIC:
+ return CXXFLAGS_VISIBILITY_PUBLIC;
+ case DEBUG_VISIBILITY_PRIVATE:
+ return CXXFLAGS_VISIBILITY_PRIVATE;
+ case DEBUG_VISIBILITY_PROTECTED:
+ return CXXFLAGS_VISIBILITY_PROTECTED;
+ }
+ /*NOTREACHED*/
+}
+
+/* Start defining a struct type. We build it in the strdef field on
+ the stack, to avoid confusing type definitions required by the
+ fields with the struct type itself. */
+
+static boolean
+ieee_start_struct_type (p, tag, id, structp, size)
+ PTR p;
+ const char *tag;
+ unsigned int id;
+ boolean structp;
+ unsigned int size;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp, ignorep;
+ boolean copy;
+ char ab[20];
+ const char *look;
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt, *ntlook;
+ struct ieee_buflist strdef;
+
+ localp = false;
+ ignorep = false;
+
+ /* We need to create a tag for internal use even if we don't want
+ one for external use. This will let us refer to an anonymous
+ struct. */
+ if (tag != NULL)
+ {
+ look = tag;
+ copy = false;
+ }
+ else
+ {
+ sprintf (ab, "__anon%u", id);
+ look = ab;
+ copy = true;
+ }
+
+ /* If we already have references to the tag, we must use the
+ existing type index. */
+ h = ieee_name_type_hash_lookup (&info->tags, look, true, copy);
+ if (h == NULL)
+ return false;
+
+ nt = NULL;
+ for (ntlook = h->types; ntlook != NULL; ntlook = ntlook->next)
+ {
+ if (ntlook->id == id)
+ nt = ntlook;
+ else if (! ntlook->type.localp)
+ {
+ /* We are creating a duplicate definition of a globally
+ defined tag. Force it to be local to avoid
+ confusion. */
+ localp = true;
+ }
+ }
+
+ if (nt != NULL)
+ {
+ assert (localp == nt->type.localp);
+ if (nt->kind == DEBUG_KIND_ILLEGAL && ! localp)
+ {
+ /* We've already seen a global definition of the type.
+ Ignore this new definition. */
+ ignorep = true;
+ }
+ }
+ else
+ {
+ nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
+ memset (nt, 0, sizeof *nt);
+ nt->id = id;
+ nt->type.name = h->root.string;
+ nt->next = h->types;
+ h->types = nt;
+ nt->type.indx = info->type_indx;
+ ++info->type_indx;
+ }
+
+ nt->kind = DEBUG_KIND_ILLEGAL;
+
+ if (! ieee_init_buffer (info, &strdef)
+ || ! ieee_define_named_type (info, tag, nt->type.indx, size, true,
+ localp, &strdef)
+ || ! ieee_write_number (info, structp ? 'S' : 'U')
+ || ! ieee_write_number (info, size))
+ return false;
+
+ if (! ignorep)
+ {
+ const char *hold;
+
+ /* We never want nt->type.name to be NULL. We want the rest of
+ the type to be the object set up on the type stack; it will
+ have a NULL name if tag is NULL. */
+ hold = nt->type.name;
+ nt->type = info->type_stack->type;
+ nt->type.name = hold;
+ }
+
+ info->type_stack->type.name = tag;
+ info->type_stack->type.strdef = strdef;
+ info->type_stack->type.ignorep = ignorep;
+
+ return true;
+}
+
+/* Add a field to a struct. */
+
+static boolean
+ieee_struct_field (p, name, bitpos, bitsize, visibility)
+ PTR p;
+ const char *name;
+ bfd_vma bitpos;
+ bfd_vma bitsize;
+ enum debug_visibility visibility;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int size;
+ boolean unsignedp;
+ boolean referencep;
+ boolean localp;
+ unsigned int indx;
+ bfd_vma offset;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->next != NULL
+ && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
+
+ /* If we are ignoring this struct definition, just pop and ignore
+ the type. */
+ if (info->type_stack->next->type.ignorep)
+ {
+ ieee_pop_unused_type (info);
+ return true;
+ }
+
+ size = info->type_stack->type.size;
+ unsignedp = info->type_stack->type.unsignedp;
+ referencep = info->type_stack->type.referencep;
+ localp = info->type_stack->type.localp;
+ indx = ieee_pop_type (info);
+
+ if (localp)
+ info->type_stack->type.localp = true;
+
+ if (info->type_stack->type.classdef != NULL)
+ {
+ unsigned int flags;
+ unsigned int nindx;
+
+ /* This is a class. We must add a description of this field to
+ the class records we are building. */
+
+ flags = ieee_vis_to_flags (visibility);
+ nindx = info->type_stack->type.classdef->indx;
+ if (! ieee_change_buffer (info,
+ &info->type_stack->type.classdef->pmiscbuf)
+ || ! ieee_write_asn (info, nindx, 'd')
+ || ! ieee_write_asn (info, nindx, flags)
+ || ! ieee_write_atn65 (info, nindx, name)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ info->type_stack->type.classdef->pmisccount += 4;
+
+ if (referencep)
+ {
+ unsigned int nindx;
+
+ /* We need to output a record recording that this field is
+ really of reference type. We put this on the refs field
+ of classdef, so that it can be appended to the C++
+ records after the class is defined. */
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+
+ if (! ieee_change_buffer (info,
+ &info->type_stack->type.classdef->refs)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, 4)
+ || ! ieee_write_asn (info, nindx, 'R')
+ || ! ieee_write_asn (info, nindx, 3)
+ || ! ieee_write_atn65 (info, nindx, info->type_stack->type.name)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ }
+ }
+
+ /* If the bitsize doesn't match the expected size, we need to output
+ a bitfield type. */
+ if (size == 0 || bitsize == 0 || bitsize == size * 8)
+ offset = bitpos / 8;
+ else
+ {
+ if (! ieee_define_type (info, 0, unsignedp,
+ info->type_stack->type.localp)
+ || ! ieee_write_number (info, 'g')
+ || ! ieee_write_number (info, unsignedp ? 0 : 1)
+ || ! ieee_write_number (info, bitsize)
+ || ! ieee_write_number (info, indx))
+ return false;
+ indx = ieee_pop_type (info);
+ offset = bitpos;
+ }
+
+ /* Switch to the struct we are building in order to output this
+ field definition. */
+ return (ieee_change_buffer (info, &info->type_stack->type.strdef)
+ && ieee_write_id (info, name)
+ && ieee_write_number (info, indx)
+ && ieee_write_number (info, offset));
+}
+
+/* Finish up a struct type. */
+
+static boolean
+ieee_end_struct_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_buflist *pb;
+
+ assert (info->type_stack != NULL
+ && ! ieee_buffer_emptyp (&info->type_stack->type.strdef));
+
+ /* If we were ignoring this struct definition because it was a
+ duplicate defintion, just through away whatever bytes we have
+ accumulated. Leave the type on the stack. */
+ if (info->type_stack->type.ignorep)
+ return true;
+
+ /* If this is not a duplicate definition of this tag, then localp
+ will be false, and we can put it in the global type block.
+ FIXME: We should avoid outputting duplicate definitions which are
+ the same. */
+ if (! info->type_stack->type.localp)
+ {
+ /* Make sure we have started the global type block. */
+ if (ieee_buffer_emptyp (&info->global_types))
+ {
+ if (! ieee_change_buffer (info, &info->global_types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 2)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, ""))
+ return false;
+ }
+ pb = &info->global_types;
+ }
+ else
+ {
+ /* Make sure we have started the types block. */
+ if (ieee_buffer_emptyp (&info->types))
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+ }
+ pb = &info->types;
+ }
+
+ /* Append the struct definition to the types. */
+ if (! ieee_append_buffer (info, pb, &info->type_stack->type.strdef)
+ || ! ieee_init_buffer (info, &info->type_stack->type.strdef))
+ return false;
+
+ /* Leave the struct on the type stack. */
+
+ return true;
+}
+
+/* Start a class type. */
+
+static boolean
+ieee_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
+ PTR p;
+ const char *tag;
+ unsigned int id;
+ boolean structp;
+ unsigned int size;
+ boolean vptr;
+ boolean ownvptr;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ const char *vclass;
+ struct ieee_buflist pmiscbuf;
+ unsigned int indx;
+ struct ieee_type_class *classdef;
+
+ /* A C++ class is output as a C++ struct along with a set of pmisc
+ records describing the class. */
+
+ /* We need to have a name so that we can associate the struct and
+ the class. */
+ if (tag == NULL)
+ {
+ char *t;
+
+ t = (char *) xmalloc (20);
+ sprintf (t, "__anon%u", id);
+ tag = t;
+ }
+
+ /* We can't write out the virtual table information until we have
+ finished the class, because we don't know the virtual table size.
+ We get the size from the largest voffset we see. */
+ vclass = NULL;
+ if (vptr && ! ownvptr)
+ {
+ vclass = info->type_stack->type.name;
+ assert (vclass != NULL);
+ /* We don't call ieee_pop_unused_type, since the class should
+ get defined. */
+ (void) ieee_pop_type (info);
+ }
+
+ if (! ieee_start_struct_type (p, tag, id, structp, size))
+ return false;
+
+ indx = info->name_indx;
+ ++info->name_indx;
+
+ /* We write out pmisc records into the classdef field. We will
+ write out the pmisc start after we know the number of records we
+ need. */
+ if (! ieee_init_buffer (info, &pmiscbuf)
+ || ! ieee_change_buffer (info, &pmiscbuf)
+ || ! ieee_write_asn (info, indx, 'T')
+ || ! ieee_write_asn (info, indx, structp ? 'o' : 'u')
+ || ! ieee_write_atn65 (info, indx, tag))
+ return false;
+
+ classdef = (struct ieee_type_class *) xmalloc (sizeof *classdef);
+ memset (classdef, 0, sizeof *classdef);
+
+ classdef->indx = indx;
+ classdef->pmiscbuf = pmiscbuf;
+ classdef->pmisccount = 3;
+ classdef->vclass = vclass;
+ classdef->ownvptr = ownvptr;
+
+ info->type_stack->type.classdef = classdef;
+
+ return true;
+}
+
+/* Add a static member to a class. */
+
+static boolean
+ieee_class_static_member (p, name, physname, visibility)
+ PTR p;
+ const char *name;
+ const char *physname;
+ enum debug_visibility visibility;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int flags;
+ unsigned int nindx;
+
+ /* We don't care about the type. Hopefully there will be a call to
+ ieee_variable declaring the physical name and the type, since
+ that is where an IEEE consumer must get the type. */
+ ieee_pop_unused_type (info);
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL);
+
+ flags = ieee_vis_to_flags (visibility);
+ flags |= CXXFLAGS_STATIC;
+
+ nindx = info->type_stack->type.classdef->indx;
+
+ if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
+ || ! ieee_write_asn (info, nindx, 'd')
+ || ! ieee_write_asn (info, nindx, flags)
+ || ! ieee_write_atn65 (info, nindx, name)
+ || ! ieee_write_atn65 (info, nindx, physname))
+ return false;
+ info->type_stack->type.classdef->pmisccount += 4;
+
+ return true;
+}
+
+/* Add a base class to a class. */
+
+static boolean
+ieee_class_baseclass (p, bitpos, virtual, visibility)
+ PTR p;
+ bfd_vma bitpos;
+ boolean virtual;
+ enum debug_visibility visibility;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ const char *bname;
+ boolean localp;
+ unsigned int bindx;
+ char *fname;
+ unsigned int flags;
+ unsigned int nindx;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.name != NULL
+ && info->type_stack->next != NULL
+ && info->type_stack->next->type.classdef != NULL
+ && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
+
+ bname = info->type_stack->type.name;
+ localp = info->type_stack->type.localp;
+ bindx = ieee_pop_type (info);
+
+ /* We are currently defining both a struct and a class. We must
+ write out a field definition in the struct which holds the base
+ class. The stabs debugging reader will create a field named
+ _vb$CLASS for a virtual base class, so we just use that. FIXME:
+ we should not depend upon a detail of stabs debugging. */
+ if (virtual)
+ {
+ fname = (char *) xmalloc (strlen (bname) + sizeof "_vb$");
+ sprintf (fname, "_vb$%s", bname);
+ flags = BASEFLAGS_VIRTUAL;
+ }
+ else
+ {
+ if (localp)
+ info->type_stack->type.localp = true;
+
+ fname = (char *) xmalloc (strlen (bname) + sizeof "_b$");
+ sprintf (fname, "_b$%s", bname);
+
+ if (! ieee_change_buffer (info, &info->type_stack->type.strdef)
+ || ! ieee_write_id (info, fname)
+ || ! ieee_write_number (info, bindx)
+ || ! ieee_write_number (info, bitpos / 8))
+ return false;
+ flags = 0;
+ }
+
+ if (visibility == DEBUG_VISIBILITY_PRIVATE)
+ flags |= BASEFLAGS_PRIVATE;
+
+ nindx = info->type_stack->type.classdef->indx;
+
+ if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
+ || ! ieee_write_asn (info, nindx, 'b')
+ || ! ieee_write_asn (info, nindx, flags)
+ || ! ieee_write_atn65 (info, nindx, bname)
+ || ! ieee_write_asn (info, nindx, 0)
+ || ! ieee_write_atn65 (info, nindx, fname))
+ return false;
+ info->type_stack->type.classdef->pmisccount += 5;
+
+ free (fname);
+
+ return true;
+}
+
+/* Start building a method for a class. */
+
+static boolean
+ieee_class_start_method (p, name)
+ PTR p;
+ const char *name;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL
+ && info->type_stack->type.classdef->method == NULL);
+
+ info->type_stack->type.classdef->method = name;
+
+ return true;
+}
+
+/* Define a new method variant, either static or not. */
+
+static boolean
+ieee_class_method_var (info, physname, visibility, staticp, constp,
+ volatilep, voffset, context)
+ struct ieee_handle *info;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean staticp;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ boolean context;
+{
+ unsigned int flags;
+ unsigned int nindx;
+ boolean virtual;
+
+ /* We don't need the type of the method. An IEEE consumer which
+ wants the type must track down the function by the physical name
+ and get the type from that. */
+ ieee_pop_unused_type (info);
+
+ /* We don't use the context. FIXME: We probably ought to use it to
+ adjust the voffset somehow, but I don't really know how. */
+ if (context)
+ ieee_pop_unused_type (info);
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL
+ && info->type_stack->type.classdef->method != NULL);
+
+ flags = ieee_vis_to_flags (visibility);
+
+ /* FIXME: We never set CXXFLAGS_OVERRIDE, CXXFLAGS_OPERATOR,
+ CXXFLAGS_CTORDTOR, CXXFLAGS_CTOR, or CXXFLAGS_INLINE. */
+
+ if (staticp)
+ flags |= CXXFLAGS_STATIC;
+ if (constp)
+ flags |= CXXFLAGS_CONST;
+ if (volatilep)
+ flags |= CXXFLAGS_VOLATILE;
+
+ nindx = info->type_stack->type.classdef->indx;
+
+ virtual = context || voffset > 0;
+
+ if (! ieee_change_buffer (info,
+ &info->type_stack->type.classdef->pmiscbuf)
+ || ! ieee_write_asn (info, nindx, virtual ? 'v' : 'm')
+ || ! ieee_write_asn (info, nindx, flags)
+ || ! ieee_write_atn65 (info, nindx,
+ info->type_stack->type.classdef->method)
+ || ! ieee_write_atn65 (info, nindx, physname))
+ return false;
+
+ if (virtual)
+ {
+ if (voffset > info->type_stack->type.classdef->voffset)
+ info->type_stack->type.classdef->voffset = voffset;
+ if (! ieee_write_asn (info, nindx, voffset))
+ return false;
+ ++info->type_stack->type.classdef->pmisccount;
+ }
+
+ if (! ieee_write_asn (info, nindx, 0))
+ return false;
+
+ info->type_stack->type.classdef->pmisccount += 5;
+
+ return true;
+}
+
+/* Define a new method variant. */
+
+static boolean
+ieee_class_method_variant (p, physname, visibility, constp, volatilep,
+ voffset, context)
+ PTR p;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ boolean context;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ return ieee_class_method_var (info, physname, visibility, false, constp,
+ volatilep, voffset, context);
+}
+
+/* Define a new static method variant. */
+
+static boolean
+ieee_class_static_method_variant (p, physname, visibility, constp, volatilep)
+ PTR p;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ return ieee_class_method_var (info, physname, visibility, true, constp,
+ volatilep, 0, false);
+}
+
+/* Finish up a method. */
+
+static boolean
+ieee_class_end_method (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL
+ && info->type_stack->type.classdef->method != NULL);
+
+ info->type_stack->type.classdef->method = NULL;
+
+ return true;
+}
+
+/* Finish up a class. */
+
+static boolean
+ieee_end_class_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int nindx;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL);
+
+ /* If we were ignoring this class definition because it was a
+ duplicate definition, just through away whatever bytes we have
+ accumulated. Leave the type on the stack. */
+ if (info->type_stack->type.ignorep)
+ return true;
+
+ nindx = info->type_stack->type.classdef->indx;
+
+ /* If we have a virtual table, we can write out the information now. */
+ if (info->type_stack->type.classdef->vclass != NULL
+ || info->type_stack->type.classdef->ownvptr)
+ {
+ if (! ieee_change_buffer (info,
+ &info->type_stack->type.classdef->pmiscbuf)
+ || ! ieee_write_asn (info, nindx, 'z')
+ || ! ieee_write_atn65 (info, nindx, "")
+ || ! ieee_write_asn (info, nindx,
+ info->type_stack->type.classdef->voffset))
+ return false;
+ if (info->type_stack->type.classdef->ownvptr)
+ {
+ if (! ieee_write_atn65 (info, nindx, ""))
+ return false;
+ }
+ else
+ {
+ if (! ieee_write_atn65 (info, nindx,
+ info->type_stack->type.classdef->vclass))
+ return false;
+ }
+ if (! ieee_write_asn (info, nindx, 0))
+ return false;
+ info->type_stack->type.classdef->pmisccount += 5;
+ }
+
+ /* Now that we know the number of pmisc records, we can write out
+ the atn62 which starts the pmisc records, and append them to the
+ C++ buffers. */
+
+ if (! ieee_change_buffer (info, &info->cxx)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info,
+ info->type_stack->type.classdef->pmisccount))
+ return false;
+
+ if (! ieee_append_buffer (info, &info->cxx,
+ &info->type_stack->type.classdef->pmiscbuf))
+ return false;
+ if (! ieee_buffer_emptyp (&info->type_stack->type.classdef->refs))
+ {
+ if (! ieee_append_buffer (info, &info->cxx,
+ &info->type_stack->type.classdef->refs))
+ return false;
+ }
+
+ return ieee_end_struct_type (p);
+}
+
+/* Push a previously seen typedef onto the type stack. */
+
+static boolean
+ieee_typedef_type (p, name)
+ PTR p;
+ const char *name;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt;
+
+ h = ieee_name_type_hash_lookup (&info->typedefs, name, false, false);
+
+ /* h should never be NULL, since that would imply that the generic
+ debugging code has asked for a typedef which it has not yet
+ defined. */
+ assert (h != NULL);
+
+ /* We always use the most recently defined type for this name, which
+ will be the first one on the list. */
+
+ nt = h->types;
+ if (! ieee_push_type (info, nt->type.indx, nt->type.size,
+ nt->type.unsignedp, nt->type.localp))
+ return false;
+
+ /* Copy over any other type information we may have. */
+ info->type_stack->type = nt->type;
+
+ return true;
+}
+
+/* Push a tagged type onto the type stack. */
+
+static boolean
+ieee_tag_type (p, name, id, kind)
+ PTR p;
+ const char *name;
+ unsigned int id;
+ enum debug_type_kind kind;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp;
+ boolean copy;
+ char ab[20];
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt;
+
+ if (kind == DEBUG_KIND_ENUM)
+ {
+ struct ieee_defined_enum *e;
+
+ if (name == NULL)
+ abort ();
+ for (e = info->enums; e != NULL; e = e->next)
+ if (e->tag != NULL && strcmp (e->tag, name) == 0)
+ return ieee_push_type (info, e->indx, 0, true, false);
+ abort ();
+ }
+
+ localp = false;
+
+ copy = false;
+ if (name == NULL)
+ {
+ sprintf (ab, "__anon%u", id);
+ name = ab;
+ copy = true;
+ }
+
+ h = ieee_name_type_hash_lookup (&info->tags, name, true, copy);
+ if (h == NULL)
+ return false;
+
+ for (nt = h->types; nt != NULL; nt = nt->next)
+ {
+ if (nt->id == id)
+ {
+ if (! ieee_push_type (info, nt->type.indx, nt->type.size,
+ nt->type.unsignedp, nt->type.localp))
+ return false;
+ /* Copy over any other type information we may have. */
+ info->type_stack->type = nt->type;
+ return true;
+ }
+
+ if (! nt->type.localp)
+ {
+ /* This is a duplicate of a global type, so it must be
+ local. */
+ localp = true;
+ }
+ }
+
+ nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
+ memset (nt, 0, sizeof *nt);
+
+ nt->id = id;
+ nt->type.name = h->root.string;
+ nt->type.indx = info->type_indx;
+ nt->type.localp = localp;
+ ++info->type_indx;
+ nt->kind = kind;
+
+ nt->next = h->types;
+ h->types = nt;
+
+ if (! ieee_push_type (info, nt->type.indx, 0, false, localp))
+ return false;
+
+ info->type_stack->type.name = h->root.string;
+
+ return true;
+}
+
+/* Output a typedef. */
+
+static boolean
+ieee_typdef (p, name)
+ PTR p;
+ const char *name;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_write_type type;
+ unsigned int indx;
+ boolean found;
+ boolean localp;
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt;
+
+ type = info->type_stack->type;
+ indx = type.indx;
+
+ /* If this is a simple builtin type using a builtin name, we don't
+ want to output the typedef itself. We also want to change the
+ type index to correspond to the name being used. We recognize
+ names used in stabs debugging output even if they don't exactly
+ correspond to the names used for the IEEE builtin types. */
+ found = false;
+ if (indx <= (unsigned int) builtin_bcd_float)
+ {
+ switch ((enum builtin_types) indx)
+ {
+ default:
+ break;
+
+ case builtin_void:
+ if (strcmp (name, "void") == 0)
+ found = true;
+ break;
+
+ case builtin_signed_char:
+ case builtin_char:
+ if (strcmp (name, "signed char") == 0)
+ {
+ indx = (unsigned int) builtin_signed_char;
+ found = true;
+ }
+ else if (strcmp (name, "char") == 0)
+ {
+ indx = (unsigned int) builtin_char;
+ found = true;
+ }
+ break;
+
+ case builtin_unsigned_char:
+ if (strcmp (name, "unsigned char") == 0)
+ found = true;
+ break;
+
+ case builtin_signed_short_int:
+ case builtin_short:
+ case builtin_short_int:
+ case builtin_signed_short:
+ if (strcmp (name, "signed short int") == 0)
+ {
+ indx = (unsigned int) builtin_signed_short_int;
+ found = true;
+ }
+ else if (strcmp (name, "short") == 0)
+ {
+ indx = (unsigned int) builtin_short;
+ found = true;
+ }
+ else if (strcmp (name, "short int") == 0)
+ {
+ indx = (unsigned int) builtin_short_int;
+ found = true;
+ }
+ else if (strcmp (name, "signed short") == 0)
+ {
+ indx = (unsigned int) builtin_signed_short;
+ found = true;
+ }
+ break;
+
+ case builtin_unsigned_short_int:
+ case builtin_unsigned_short:
+ if (strcmp (name, "unsigned short int") == 0
+ || strcmp (name, "short unsigned int") == 0)
+ {
+ indx = builtin_unsigned_short_int;
+ found = true;
+ }
+ else if (strcmp (name, "unsigned short") == 0)
+ {
+ indx = builtin_unsigned_short;
+ found = true;
+ }
+ break;
+
+ case builtin_signed_long:
+ case builtin_int: /* FIXME: Size depends upon architecture. */
+ case builtin_long:
+ if (strcmp (name, "signed long") == 0)
+ {
+ indx = builtin_signed_long;
+ found = true;
+ }
+ else if (strcmp (name, "int") == 0)
+ {
+ indx = builtin_int;
+ found = true;
+ }
+ else if (strcmp (name, "long") == 0
+ || strcmp (name, "long int") == 0)
+ {
+ indx = builtin_long;
+ found = true;
+ }
+ break;
+
+ case builtin_unsigned_long:
+ case builtin_unsigned: /* FIXME: Size depends upon architecture. */
+ case builtin_unsigned_int: /* FIXME: Like builtin_unsigned. */
+ if (strcmp (name, "unsigned long") == 0
+ || strcmp (name, "long unsigned int") == 0)
+ {
+ indx = builtin_unsigned_long;
+ found = true;
+ }
+ else if (strcmp (name, "unsigned") == 0)
+ {
+ indx = builtin_unsigned;
+ found = true;
+ }
+ else if (strcmp (name, "unsigned int") == 0)
+ {
+ indx = builtin_unsigned_int;
+ found = true;
+ }
+ break;
+
+ case builtin_signed_long_long:
+ if (strcmp (name, "signed long long") == 0
+ || strcmp (name, "long long int") == 0)
+ found = true;
+ break;
+
+ case builtin_unsigned_long_long:
+ if (strcmp (name, "unsigned long long") == 0
+ || strcmp (name, "long long unsigned int") == 0)
+ found = true;
+ break;
+
+ case builtin_float:
+ if (strcmp (name, "float") == 0)
+ found = true;
+ break;
+
+ case builtin_double:
+ if (strcmp (name, "double") == 0)
+ found = true;
+ break;
+
+ case builtin_long_double:
+ if (strcmp (name, "long double") == 0)
+ found = true;
+ break;
+
+ case builtin_long_long_double:
+ if (strcmp (name, "long long double") == 0)
+ found = true;
+ break;
+ }
+
+ if (found)
+ type.indx = indx;
+ }
+
+ h = ieee_name_type_hash_lookup (&info->typedefs, name, true, false);
+ if (h == NULL)
+ return false;
+
+ /* See if we have already defined this type with this name. */
+ localp = type.localp;
+ for (nt = h->types; nt != NULL; nt = nt->next)
+ {
+ if (nt->id == indx)
+ {
+ /* If this is a global definition, then we don't need to
+ do anything here. */
+ if (! nt->type.localp)
+ {
+ ieee_pop_unused_type (info);
+ return true;
+ }
+ }
+ else
+ {
+ /* This is a duplicate definition, so make this one local. */
+ localp = true;
+ }
+ }
+
+ /* We need to add a new typedef for this type. */
+
+ nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
+ memset (nt, 0, sizeof *nt);
+ nt->id = indx;
+ nt->type = type;
+ nt->type.name = name;
+ nt->type.localp = localp;
+ nt->kind = DEBUG_KIND_ILLEGAL;
+
+ nt->next = h->types;
+ h->types = nt;
+
+ if (found)
+ {
+ /* This is one of the builtin typedefs, so we don't need to
+ actually define it. */
+ ieee_pop_unused_type (info);
+ return true;
+ }
+
+ indx = ieee_pop_type (info);
+
+ if (! ieee_define_named_type (info, name, (unsigned int) -1, type.size,
+ type.unsignedp, localp,
+ (struct ieee_buflist *) NULL)
+ || ! ieee_write_number (info, 'T')
+ || ! ieee_write_number (info, indx))
+ return false;
+
+ /* Remove the type we just added to the type stack. This should not
+ be ieee_pop_unused_type, since the type is used, we just don't
+ need it now. */
+ (void) ieee_pop_type (info);
+
+ return true;
+}
+
+/* Output a tag for a type. We don't have to do anything here. */
+
+static boolean
+ieee_tag (p, name)
+ PTR p;
+ const char *name;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ /* This should not be ieee_pop_unused_type, since we want the type
+ to be defined. */
+ (void) ieee_pop_type (info);
+ return true;
+}
+
+/* Output an integer constant. */
+
+static boolean
+ieee_int_constant (p, name, val)
+ PTR p;
+ const char *name;
+ bfd_vma val;
+{
+ /* FIXME. */
+ return true;
+}
+
+/* Output a floating point constant. */
+
+static boolean
+ieee_float_constant (p, name, val)
+ PTR p;
+ const char *name;
+ double val;
+{
+ /* FIXME. */
+ return true;
+}
+
+/* Output a typed constant. */
+
+static boolean
+ieee_typed_constant (p, name, val)
+ PTR p;
+ const char *name;
+ bfd_vma val;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ /* FIXME. */
+ ieee_pop_unused_type (info);
+ return true;
+}
+
+/* Output a variable. */
+
+static boolean
+ieee_variable (p, name, kind, val)
+ PTR p;
+ const char *name;
+ enum debug_var_kind kind;
+ bfd_vma val;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int name_indx;
+ unsigned int size;
+ boolean referencep;
+ unsigned int type_indx;
+ boolean asn;
+ int refflag;
+
+ size = info->type_stack->type.size;
+ referencep = info->type_stack->type.referencep;
+ type_indx = ieee_pop_type (info);
+
+ assert (! ieee_buffer_emptyp (&info->vars));
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+
+ name_indx = info->name_indx;
+ ++info->name_indx;
+
+ /* Write out an NN and an ATN record for this variable. */
+ if (! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, name_indx)
+ || ! ieee_write_id (info, name)
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, name_indx)
+ || ! ieee_write_number (info, type_indx))
+ return false;
+ switch (kind)
+ {
+ default:
+ abort ();
+ return false;
+ case DEBUG_GLOBAL:
+ if (! ieee_write_number (info, 8)
+ || ! ieee_add_range (info, false, val, val + size))
+ return false;
+ refflag = 0;
+ asn = true;
+ break;
+ case DEBUG_STATIC:
+ if (! ieee_write_number (info, 3)
+ || ! ieee_add_range (info, false, val, val + size))
+ return false;
+ refflag = 1;
+ asn = true;
+ break;
+ case DEBUG_LOCAL_STATIC:
+ if (! ieee_write_number (info, 3)
+ || ! ieee_add_range (info, false, val, val + size))
+ return false;
+ refflag = 2;
+ asn = true;
+ break;
+ case DEBUG_LOCAL:
+ if (! ieee_write_number (info, 1)
+ || ! ieee_write_number (info, val))
+ return false;
+ refflag = 2;
+ asn = false;
+ break;
+ case DEBUG_REGISTER:
+ if (! ieee_write_number (info, 2)
+ || ! ieee_write_number (info,
+ ieee_genreg_to_regno (info->abfd, val)))
+ return false;
+ refflag = 2;
+ asn = false;
+ break;
+ }
+
+ if (asn)
+ {
+ if (! ieee_write_asn (info, name_indx, val))
+ return false;
+ }
+
+ /* If this is really a reference type, then we just output it with
+ pointer type, and must now output a C++ record indicating that it
+ is really reference type. */
+ if (referencep)
+ {
+ unsigned int nindx;
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+
+ /* If this is a global variable, we want to output the misc
+ record in the C++ misc record block. Otherwise, we want to
+ output it just after the variable definition, which is where
+ the current buffer is. */
+ if (refflag != 2)
+ {
+ if (! ieee_change_buffer (info, &info->cxx))
+ return false;
+ }
+
+ if (! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, 3)
+ || ! ieee_write_asn (info, nindx, 'R')
+ || ! ieee_write_asn (info, nindx, refflag)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ }
+
+ return true;
+}
+
+/* Start outputting information for a function. */
+
+static boolean
+ieee_start_function (p, name, global)
+ PTR p;
+ const char *name;
+ boolean global;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean referencep;
+ unsigned int retindx, typeindx;
+
+ referencep = info->type_stack->type.referencep;
+ retindx = ieee_pop_type (info);
+
+ /* Besides recording a BB4 or BB6 block, we record the type of the
+ function in the BB1 typedef block. We can't write out the full
+ type until we have seen all the parameters, so we accumulate it
+ in info->fntype and info->fnargs. */
+ if (! ieee_buffer_emptyp (&info->fntype))
+ {
+ /* FIXME: This might happen someday if we support nested
+ functions. */
+ abort ();
+ }
+
+ info->fnname = name;
+
+ /* An attribute of 0x40 means that the push mask is unknown. */
+ if (! ieee_define_named_type (info, name, (unsigned int) -1, 0, false, true,
+ &info->fntype)
+ || ! ieee_write_number (info, 'x')
+ || ! ieee_write_number (info, 0x40)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, retindx))
+ return false;
+
+ typeindx = ieee_pop_type (info);
+
+ if (! ieee_init_buffer (info, &info->fnargs))
+ return false;
+ info->fnargcount = 0;
+
+ /* If the function return value is actually a reference type, we
+ must add a record indicating that. */
+ if (referencep)
+ {
+ unsigned int nindx;
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_change_buffer (info, &info->cxx)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, 3)
+ || ! ieee_write_asn (info, nindx, 'R')
+ || ! ieee_write_asn (info, nindx, global ? 0 : 1)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ }
+
+ assert (! ieee_buffer_emptyp (&info->vars));
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+
+ /* The address is written out as the first block. */
+
+ ++info->block_depth;
+
+ return (ieee_write_byte (info, (int) ieee_bb_record_enum)
+ && ieee_write_byte (info, global ? 4 : 6)
+ && ieee_write_number (info, 0)
+ && ieee_write_id (info, name)
+ && ieee_write_number (info, 0)
+ && ieee_write_number (info, typeindx));
+}
+
+/* Add a function parameter. This will normally be called before the
+ first block, so we postpone them until we see the block. */
+
+static boolean
+ieee_function_parameter (p, name, kind, val)
+ PTR p;
+ const char *name;
+ enum debug_parm_kind kind;
+ bfd_vma val;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_pending_parm *m, **pm;
+
+ assert (info->block_depth == 1);
+
+ m = (struct ieee_pending_parm *) xmalloc (sizeof *m);
+ memset (m, 0, sizeof *m);
+
+ m->next = NULL;
+ m->name = name;
+ m->referencep = info->type_stack->type.referencep;
+ m->type = ieee_pop_type (info);
+ m->kind = kind;
+ m->val = val;
+
+ for (pm = &info->pending_parms; *pm != NULL; pm = &(*pm)->next)
+ ;
+ *pm = m;
+
+ /* Add the type to the fnargs list. */
+ if (! ieee_change_buffer (info, &info->fnargs)
+ || ! ieee_write_number (info, m->type))
+ return false;
+ ++info->fnargcount;
+
+ return true;
+}
+
+/* Output pending function parameters. */
+
+static boolean
+ieee_output_pending_parms (info)
+ struct ieee_handle *info;
+{
+ struct ieee_pending_parm *m;
+ unsigned int refcount;
+
+ refcount = 0;
+ for (m = info->pending_parms; m != NULL; m = m->next)
+ {
+ enum debug_var_kind vkind;
+
+ switch (m->kind)
+ {
+ default:
+ abort ();
+ return false;
+ case DEBUG_PARM_STACK:
+ case DEBUG_PARM_REFERENCE:
+ vkind = DEBUG_LOCAL;
+ break;
+ case DEBUG_PARM_REG:
+ case DEBUG_PARM_REF_REG:
+ vkind = DEBUG_REGISTER;
+ break;
+ }
+
+ if (! ieee_push_type (info, m->type, 0, false, false))
+ return false;
+ info->type_stack->type.referencep = m->referencep;
+ if (m->referencep)
+ ++refcount;
+ if (! ieee_variable ((PTR) info, m->name, vkind, m->val))
+ return false;
+ }
+
+ /* If there are any reference parameters, we need to output a
+ miscellaneous record indicating them. */
+ if (refcount > 0)
+ {
+ unsigned int nindx, varindx;
+
+ /* FIXME: The MRI compiler outputs the demangled function name
+ here, but we are outputting the mangled name. */
+ nindx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, refcount + 3)
+ || ! ieee_write_asn (info, nindx, 'B')
+ || ! ieee_write_atn65 (info, nindx, info->fnname)
+ || ! ieee_write_asn (info, nindx, 0))
+ return false;
+ for (m = info->pending_parms, varindx = 1;
+ m != NULL;
+ m = m->next, varindx++)
+ {
+ if (m->referencep)
+ {
+ if (! ieee_write_asn (info, nindx, varindx))
+ return false;
+ }
+ }
+ }
+
+ m = info->pending_parms;
+ while (m != NULL)
+ {
+ struct ieee_pending_parm *next;
+
+ next = m->next;
+ free (m);
+ m = next;
+ }
+
+ info->pending_parms = NULL;
+
+ return true;
+}
+
+/* Start a block. If this is the first block, we output the address
+ to finish the BB4 or BB6, and then output the function parameters. */
+
+static boolean
+ieee_start_block (p, addr)
+ PTR p;
+ bfd_vma addr;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+
+ if (info->block_depth == 1)
+ {
+ if (! ieee_write_number (info, addr)
+ || ! ieee_output_pending_parms (info))
+ return false;
+ }
+ else
+ {
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 6)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, addr))
+ return false;
+ }
+
+ if (! ieee_start_range (info, addr))
+ return false;
+
+ ++info->block_depth;
+
+ return true;
+}
+
+/* End a block. */
+
+static boolean
+ieee_end_block (p, addr)
+ PTR p;
+ bfd_vma addr;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ /* The address we are given is the end of the block, but IEEE seems
+ to want to the address of the last byte in the block, so we
+ subtract one. */
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+ || ! ieee_write_number (info, addr - 1))
+ return false;
+
+ if (! ieee_end_range (info, addr))
+ return false;
+
+ --info->block_depth;
+
+ if (addr > info->highaddr)
+ info->highaddr = addr;
+
+ return true;
+}
+
+/* End a function. */
+
+static boolean
+ieee_end_function (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ assert (info->block_depth == 1);
+
+ --info->block_depth;
+
+ /* Now we can finish up fntype, and add it to the typdef section.
+ At this point, fntype is the 'x' type up to the argument count,
+ and fnargs is the argument types. We must add the argument
+ count, and we must add the level. FIXME: We don't record varargs
+ functions correctly. In fact, stabs debugging does not give us
+ enough information to do so. */
+ if (! ieee_change_buffer (info, &info->fntype)
+ || ! ieee_write_number (info, info->fnargcount)
+ || ! ieee_change_buffer (info, &info->fnargs)
+ || ! ieee_write_number (info, 0))
+ return false;
+
+ /* Make sure the typdef block has been started. */
+ if (ieee_buffer_emptyp (&info->types))
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+ }
+
+ if (! ieee_append_buffer (info, &info->types, &info->fntype)
+ || ! ieee_append_buffer (info, &info->types, &info->fnargs))
+ return false;
+
+ info->fnname = NULL;
+ if (! ieee_init_buffer (info, &info->fntype)
+ || ! ieee_init_buffer (info, &info->fnargs))
+ return false;
+ info->fnargcount = 0;
+
+ return true;
+}
+
+/* Record line number information. */
+
+static boolean
+ieee_lineno (p, filename, lineno, addr)
+ PTR p;
+ const char *filename;
+ unsigned long lineno;
+ bfd_vma addr;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ assert (info->filename != NULL);
+
+ /* The HP simulator seems to get confused when more than one line is
+ listed for the same address, at least if they are in different
+ files. We handle this by always listing the last line for a
+ given address, since that seems to be the one that gdb uses. */
+ if (info->pending_lineno_filename != NULL
+ && addr != info->pending_lineno_addr)
+ {
+ /* Make sure we have a line number block. */
+ if (! ieee_buffer_emptyp (&info->linenos))
+ {
+ if (! ieee_change_buffer (info, &info->linenos))
+ return false;
+ }
+ else
+ {
+ info->lineno_name_indx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_change_buffer (info, &info->linenos)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 5)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->filename)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, info->lineno_name_indx)
+ || ! ieee_write_id (info, ""))
+ return false;
+ info->lineno_filename = info->filename;
+ }
+
+ if (strcmp (info->pending_lineno_filename, info->lineno_filename) != 0)
+ {
+ if (strcmp (info->filename, info->lineno_filename) != 0)
+ {
+ /* We were not in the main file. Close the block for the
+ included file. */
+ if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ if (strcmp (info->filename, info->pending_lineno_filename) == 0)
+ {
+ /* We need a new NN record, and we aren't about to
+ output one. */
+ info->lineno_name_indx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, info->lineno_name_indx)
+ || ! ieee_write_id (info, ""))
+ return false;
+ }
+ }
+ if (strcmp (info->filename, info->pending_lineno_filename) != 0)
+ {
+ /* We are not changing to the main file. Open a block for
+ the new included file. */
+ info->lineno_name_indx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 5)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->pending_lineno_filename)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, info->lineno_name_indx)
+ || ! ieee_write_id (info, ""))
+ return false;
+ }
+ info->lineno_filename = info->pending_lineno_filename;
+ }
+
+ if (! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, info->lineno_name_indx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 7)
+ || ! ieee_write_number (info, info->pending_lineno)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_asn (info, info->lineno_name_indx,
+ info->pending_lineno_addr))
+ return false;
+ }
+
+ info->pending_lineno_filename = filename;
+ info->pending_lineno = lineno;
+ info->pending_lineno_addr = addr;
+
+ return true;
+}
diff --git a/gnu/usr.bin/binutils/binutils/prdbg.c b/gnu/usr.bin/binutils/binutils/prdbg.c
new file mode 100644
index 00000000000..d82791b524b
--- /dev/null
+++ b/gnu/usr.bin/binutils/binutils/prdbg.c
@@ -0,0 +1,1859 @@
+/* prdbg.c -- Print out generic debugging information.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ 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. */
+
+/* This file prints out the generic debugging information, by
+ supplying a set of routines to debug_write. */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* This is the structure we use as a handle for these routines. */
+
+struct pr_handle
+{
+ /* File to print information to. */
+ FILE *f;
+ /* Current indentation level. */
+ unsigned int indent;
+ /* Type stack. */
+ struct pr_stack *stack;
+ /* Parameter number we are about to output. */
+ int parameter;
+};
+
+/* The type stack. */
+
+struct pr_stack
+{
+ /* Next element on the stack. */
+ struct pr_stack *next;
+ /* This element. */
+ char *type;
+ /* Current visibility of fields if this is a class. */
+ enum debug_visibility visibility;
+ /* Name of the current method we are handling. */
+ const char *method;
+};
+
+static void indent PARAMS ((struct pr_handle *));
+static boolean push_type PARAMS ((struct pr_handle *, const char *));
+static boolean prepend_type PARAMS ((struct pr_handle *, const char *));
+static boolean append_type PARAMS ((struct pr_handle *, const char *));
+static boolean substitute_type PARAMS ((struct pr_handle *, const char *));
+static boolean indent_type PARAMS ((struct pr_handle *));
+static char *pop_type PARAMS ((struct pr_handle *));
+static void print_vma PARAMS ((bfd_vma, char *, boolean, boolean));
+static boolean pr_fix_visibility
+ PARAMS ((struct pr_handle *, enum debug_visibility));
+
+static boolean pr_start_compilation_unit PARAMS ((PTR, const char *));
+static boolean pr_start_source PARAMS ((PTR, const char *));
+static boolean pr_empty_type PARAMS ((PTR));
+static boolean pr_void_type PARAMS ((PTR));
+static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean));
+static boolean pr_float_type PARAMS ((PTR, unsigned int));
+static boolean pr_complex_type PARAMS ((PTR, unsigned int));
+static boolean pr_bool_type PARAMS ((PTR, unsigned int));
+static boolean pr_enum_type
+ PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
+static boolean pr_pointer_type PARAMS ((PTR));
+static boolean pr_function_type PARAMS ((PTR, int, boolean));
+static boolean pr_reference_type PARAMS ((PTR));
+static boolean pr_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+static boolean pr_array_type
+ PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean));
+static boolean pr_set_type PARAMS ((PTR, boolean));
+static boolean pr_offset_type PARAMS ((PTR));
+static boolean pr_method_type PARAMS ((PTR, boolean, int, boolean));
+static boolean pr_const_type PARAMS ((PTR));
+static boolean pr_volatile_type PARAMS ((PTR));
+static boolean pr_start_struct_type
+ PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
+static boolean pr_struct_field
+ PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static boolean pr_end_struct_type PARAMS ((PTR));
+static boolean pr_start_class_type
+ PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
+ boolean));
+static boolean pr_class_static_member
+ PARAMS ((PTR, const char *, const char *, enum debug_visibility));
+static boolean pr_class_baseclass
+ PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility));
+static boolean pr_class_start_method PARAMS ((PTR, const char *));
+static boolean pr_class_method_variant
+ PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean,
+ bfd_vma, boolean));
+static boolean pr_class_static_method_variant
+ PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean));
+static boolean pr_class_end_method PARAMS ((PTR));
+static boolean pr_end_class_type PARAMS ((PTR));
+static boolean pr_typedef_type PARAMS ((PTR, const char *));
+static boolean pr_tag_type
+ PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
+static boolean pr_typdef PARAMS ((PTR, const char *));
+static boolean pr_tag PARAMS ((PTR, const char *));
+static boolean pr_int_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean pr_float_constant PARAMS ((PTR, const char *, double));
+static boolean pr_typed_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean pr_variable
+ PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
+static boolean pr_start_function PARAMS ((PTR, const char *, boolean));
+static boolean pr_function_parameter
+ PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
+static boolean pr_start_block PARAMS ((PTR, bfd_vma));
+static boolean pr_end_block PARAMS ((PTR, bfd_vma));
+static boolean pr_end_function PARAMS ((PTR));
+static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+
+static const struct debug_write_fns pr_fns =
+{
+ pr_start_compilation_unit,
+ pr_start_source,
+ pr_empty_type,
+ pr_void_type,
+ pr_int_type,
+ pr_float_type,
+ pr_complex_type,
+ pr_bool_type,
+ pr_enum_type,
+ pr_pointer_type,
+ pr_function_type,
+ pr_reference_type,
+ pr_range_type,
+ pr_array_type,
+ pr_set_type,
+ pr_offset_type,
+ pr_method_type,
+ pr_const_type,
+ pr_volatile_type,
+ pr_start_struct_type,
+ pr_struct_field,
+ pr_end_struct_type,
+ pr_start_class_type,
+ pr_class_static_member,
+ pr_class_baseclass,
+ pr_class_start_method,
+ pr_class_method_variant,
+ pr_class_static_method_variant,
+ pr_class_end_method,
+ pr_end_class_type,
+ pr_typedef_type,
+ pr_tag_type,
+ pr_typdef,
+ pr_tag,
+ pr_int_constant,
+ pr_float_constant,
+ pr_typed_constant,
+ pr_variable,
+ pr_start_function,
+ pr_function_parameter,
+ pr_start_block,
+ pr_end_block,
+ pr_end_function,
+ pr_lineno
+};
+
+/* Print out the generic debugging information recorded in dhandle. */
+
+boolean
+print_debugging_info (f, dhandle)
+ FILE *f;
+ PTR dhandle;
+{
+ struct pr_handle info;
+
+ info.f = f;
+ info.indent = 0;
+ info.stack = NULL;
+ info.parameter = 0;
+
+ return debug_write (dhandle, &pr_fns, (PTR) &info);
+}
+
+/* Indent to the current indentation level. */
+
+static void
+indent (info)
+ struct pr_handle *info;
+{
+ unsigned int i;
+
+ for (i = 0; i < info->indent; i++)
+ putc (' ', info->f);
+}
+
+/* Push a type on the type stack. */
+
+static boolean
+push_type (info, type)
+ struct pr_handle *info;
+ const char *type;
+{
+ struct pr_stack *n;
+
+ if (type == NULL)
+ return false;
+
+ n = (struct pr_stack *) xmalloc (sizeof *n);
+ memset (n, 0, sizeof *n);
+
+ n->type = xstrdup (type);
+ n->visibility = DEBUG_VISIBILITY_IGNORE;
+ n->method = NULL;
+ n->next = info->stack;
+ info->stack = n;
+
+ return true;
+}
+
+/* Prepend a string onto the type on the top of the type stack. */
+
+static boolean
+prepend_type (info, s)
+ struct pr_handle *info;
+ const char *s;
+{
+ char *n;
+
+ assert (info->stack != NULL);
+
+ n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1);
+ sprintf (n, "%s%s", s, info->stack->type);
+ free (info->stack->type);
+ info->stack->type = n;
+
+ return true;
+}
+
+/* Append a string to the type on the top of the type stack. */
+
+static boolean
+append_type (info, s)
+ struct pr_handle *info;
+ const char *s;
+{
+ unsigned int len;
+
+ if (s == NULL)
+ return false;
+
+ assert (info->stack != NULL);
+
+ len = strlen (info->stack->type);
+ info->stack->type = (char *) xrealloc (info->stack->type,
+ len + strlen (s) + 1);
+ strcpy (info->stack->type + len, s);
+
+ return true;
+}
+
+/* We use an underscore to indicate where the name should go in a type
+ string. This function substitutes a string for the underscore. If
+ there is no underscore, the name follows the type. */
+
+static boolean
+substitute_type (info, s)
+ struct pr_handle *info;
+ const char *s;
+{
+ char *u;
+
+ assert (info->stack != NULL);
+
+ u = strchr (info->stack->type, '|');
+ if (u != NULL)
+ {
+ char *n;
+
+ n = (char *) xmalloc (strlen (info->stack->type) + strlen (s));
+
+ memcpy (n, info->stack->type, u - info->stack->type);
+ strcpy (n + (u - info->stack->type), s);
+ strcat (n, u + 1);
+
+ free (info->stack->type);
+ info->stack->type = n;
+
+ return true;
+ }
+
+ if (strchr (s, '|') != NULL
+ && (strchr (info->stack->type, '{') != NULL
+ || strchr (info->stack->type, '(') != NULL))
+ {
+ if (! prepend_type (info, "(")
+ || ! append_type (info, ")"))
+ return false;
+ }
+
+ if (*s == '\0')
+ return true;
+
+ return (append_type (info, " ")
+ && append_type (info, s));
+}
+
+/* Indent the type at the top of the stack by appending spaces. */
+
+static boolean
+indent_type (info)
+ struct pr_handle *info;
+{
+ unsigned int i;
+
+ for (i = 0; i < info->indent; i++)
+ {
+ if (! append_type (info, " "))
+ return false;
+ }
+
+ return true;
+}
+
+/* Pop a type from the type stack. */
+
+static char *
+pop_type (info)
+ struct pr_handle *info;
+{
+ struct pr_stack *o;
+ char *ret;
+
+ assert (info->stack != NULL);
+
+ o = info->stack;
+ info->stack = o->next;
+ ret = o->type;
+ free (o);
+
+ return ret;
+}
+
+/* Print a VMA value into a string. */
+
+static void
+print_vma (vma, buf, unsignedp, hexp)
+ bfd_vma vma;
+ char *buf;
+ boolean unsignedp;
+ boolean hexp;
+{
+ if (sizeof (vma) <= sizeof (unsigned long))
+ {
+ if (hexp)
+ sprintf (buf, "0x%lx", (unsigned long) vma);
+ else if (unsignedp)
+ sprintf (buf, "%lu", (unsigned long) vma);
+ else
+ sprintf (buf, "%ld", (long) vma);
+ }
+ else
+ {
+ buf[0] = '0';
+ buf[1] = 'x';
+ sprintf_vma (buf + 2, vma);
+ }
+}
+
+/* Start a new compilation unit. */
+
+static boolean
+pr_start_compilation_unit (p, filename)
+ PTR p;
+ const char *filename;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ assert (info->indent == 0);
+
+ fprintf (info->f, "%s:\n", filename);
+
+ return true;
+}
+
+/* Start a source file within a compilation unit. */
+
+static boolean
+pr_start_source (p, filename)
+ PTR p;
+ const char *filename;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ assert (info->indent == 0);
+
+ fprintf (info->f, " %s:\n", filename);
+
+ return true;
+}
+
+/* Push an empty type onto the type stack. */
+
+static boolean
+pr_empty_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ return push_type (info, "<undefined>");
+}
+
+/* Push a void type onto the type stack. */
+
+static boolean
+pr_void_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ return push_type (info, "void");
+}
+
+/* Push an integer type onto the type stack. */
+
+static boolean
+pr_int_type (p, size, unsignedp)
+ PTR p;
+ unsigned int size;
+ boolean unsignedp;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[10];
+
+ sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8);
+ return push_type (info, ab);
+}
+
+/* Push a floating type onto the type stack. */
+
+static boolean
+pr_float_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[10];
+
+ if (size == 4)
+ return push_type (info, "float");
+ else if (size == 8)
+ return push_type (info, "double");
+
+ sprintf (ab, "float%d", size * 8);
+ return push_type (info, ab);
+}
+
+/* Push a complex type onto the type stack. */
+
+static boolean
+pr_complex_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ if (! pr_float_type (p, size))
+ return false;
+
+ return prepend_type (info, "complex ");
+}
+
+/* Push a boolean type onto the type stack. */
+
+static boolean
+pr_bool_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[10];
+
+ sprintf (ab, "bool%d", size * 8);
+
+ return push_type (info, ab);
+}
+
+/* Push an enum type onto the type stack. */
+
+static boolean
+pr_enum_type (p, tag, names, values)
+ PTR p;
+ const char *tag;
+ const char **names;
+ bfd_signed_vma *values;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ unsigned int i;
+ bfd_signed_vma val;
+
+ if (! push_type (info, "enum "))
+ return false;
+ if (tag != NULL)
+ {
+ if (! append_type (info, tag)
+ || ! append_type (info, " "))
+ return false;
+ }
+ if (! append_type (info, "{ "))
+ return false;
+
+ if (names == NULL)
+ {
+ if (! append_type (info, "/* undefined */"))
+ return false;
+ }
+ else
+ {
+ val = 0;
+ for (i = 0; names[i] != NULL; i++)
+ {
+ if (i > 0)
+ {
+ if (! append_type (info, ", "))
+ return false;
+ }
+
+ if (! append_type (info, names[i]))
+ return false;
+
+ if (values[i] != val)
+ {
+ char ab[20];
+
+ print_vma (values[i], ab, false, false);
+ if (! append_type (info, " = ")
+ || ! append_type (info, ab))
+ return false;
+ val = values[i];
+ }
+
+ ++val;
+ }
+ }
+
+ return append_type (info, " }");
+}
+
+/* Turn the top type on the stack into a pointer. */
+
+static boolean
+pr_pointer_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *s;
+
+ assert (info->stack != NULL);
+
+ s = strchr (info->stack->type, '|');
+ if (s != NULL && s[1] == '[')
+ return substitute_type (info, "(*|)");
+ return substitute_type (info, "*|");
+}
+
+/* Turn the top type on the stack into a function returning that type. */
+
+static boolean
+pr_function_type (p, argcount, varargs)
+ PTR p;
+ int argcount;
+ boolean varargs;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char **arg_types;
+ unsigned int len;
+ char *s;
+
+ assert (info->stack != NULL);
+
+ len = 10;
+
+ if (argcount <= 0)
+ {
+ arg_types = NULL;
+ len += 15;
+ }
+ else
+ {
+ int i;
+
+ arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
+ for (i = argcount - 1; i >= 0; i--)
+ {
+ if (! substitute_type (info, ""))
+ return false;
+ arg_types[i] = pop_type (info);
+ if (arg_types[i] == NULL)
+ return false;
+ len += strlen (arg_types[i]) + 2;
+ }
+ if (varargs)
+ len += 5;
+ }
+
+ /* Now the return type is on the top of the stack. */
+
+ s = (char *) xmalloc (len);
+ strcpy (s, "(|) (");
+
+ if (argcount < 0)
+ strcat (s, "/* unknown */");
+ else
+ {
+ int i;
+
+ for (i = 0; i < argcount; i++)
+ {
+ if (i > 0)
+ strcat (s, ", ");
+ strcat (s, arg_types[i]);
+ }
+ if (varargs)
+ {
+ if (i > 0)
+ strcat (s, ", ");
+ strcat (s, "...");
+ }
+ if (argcount > 0)
+ free (arg_types);
+ }
+
+ strcat (s, ")");
+
+ if (! substitute_type (info, s))
+ return false;
+
+ free (s);
+
+ return true;
+}
+
+/* Turn the top type on the stack into a reference to that type. */
+
+static boolean
+pr_reference_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ assert (info->stack != NULL);
+
+ return substitute_type (info, "&|");
+}
+
+/* Make a range type. */
+
+static boolean
+pr_range_type (p, lower, upper)
+ PTR p;
+ bfd_signed_vma lower;
+ bfd_signed_vma upper;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char abl[20], abu[20];
+
+ assert (info->stack != NULL);
+
+ if (! substitute_type (info, ""))
+ return false;
+
+ print_vma (lower, abl, false, false);
+ print_vma (upper, abu, false, false);
+
+ return (prepend_type (info, "range (")
+ && append_type (info, "):")
+ && append_type (info, abl)
+ && append_type (info, ":")
+ && append_type (info, abu));
+}
+
+/* Make an array type. */
+
+/*ARGSUSED*/
+static boolean
+pr_array_type (p, lower, upper, stringp)
+ PTR p;
+ bfd_signed_vma lower;
+ bfd_signed_vma upper;
+ boolean stringp;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *range_type;
+ char abl[20], abu[20], ab[50];
+
+ range_type = pop_type (info);
+ if (range_type == NULL)
+ return false;
+
+ if (lower == 0)
+ {
+ if (upper == -1)
+ sprintf (ab, "|[]");
+ else
+ {
+ print_vma (upper + 1, abu, false, false);
+ sprintf (ab, "|[%s]", abu);
+ }
+ }
+ else
+ {
+ print_vma (lower, abl, false, false);
+ print_vma (upper, abu, false, false);
+ sprintf (ab, "|[%s:%s]", abl, abu);
+ }
+
+ if (! substitute_type (info, ab))
+ return false;
+
+ if (strcmp (range_type, "int") != 0)
+ {
+ if (! append_type (info, ":")
+ || ! append_type (info, range_type))
+ return false;
+ }
+
+ if (stringp)
+ {
+ if (! append_type (info, " /* string */"))
+ return false;
+ }
+
+ return true;
+}
+
+/* Make a set type. */
+
+/*ARGSUSED*/
+static boolean
+pr_set_type (p, bitstringp)
+ PTR p;
+ boolean bitstringp;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ if (! substitute_type (info, ""))
+ return false;
+
+ if (! prepend_type (info, "set { ")
+ || ! append_type (info, " }"))
+ return false;
+
+ if (bitstringp)
+ {
+ if (! append_type (info, "/* bitstring */"))
+ return false;
+ }
+
+ return true;
+}
+
+/* Make an offset type. */
+
+static boolean
+pr_offset_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+
+ if (! substitute_type (info, ""))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ return (substitute_type (info, "")
+ && prepend_type (info, " ")
+ && prepend_type (info, t)
+ && append_type (info, "::|"));
+}
+
+/* Make a method type. */
+
+static boolean
+pr_method_type (p, domain, argcount, varargs)
+ PTR p;
+ boolean domain;
+ int argcount;
+ boolean varargs;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ unsigned int len;
+ char *domain_type;
+ char **arg_types;
+ char *s;
+
+ len = 10;
+
+ if (! domain)
+ domain_type = NULL;
+ else
+ {
+ if (! substitute_type (info, ""))
+ return false;
+ domain_type = pop_type (info);
+ if (domain_type == NULL)
+ return false;
+ if (strncmp (domain_type, "class ", sizeof "class " - 1) == 0
+ && strchr (domain_type + sizeof "class " - 1, ' ') == NULL)
+ domain_type += sizeof "class " - 1;
+ else if (strncmp (domain_type, "union class ",
+ sizeof "union class ") == 0
+ && (strchr (domain_type + sizeof "union class " - 1, ' ')
+ == NULL))
+ domain_type += sizeof "union class " - 1;
+ len += strlen (domain_type);
+ }
+
+ if (argcount <= 0)
+ {
+ arg_types = NULL;
+ len += 15;
+ }
+ else
+ {
+ int i;
+
+ arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
+ for (i = argcount - 1; i >= 0; i--)
+ {
+ if (! substitute_type (info, ""))
+ return false;
+ arg_types[i] = pop_type (info);
+ if (arg_types[i] == NULL)
+ return false;
+ len += strlen (arg_types[i]) + 2;
+ }
+ if (varargs)
+ len += 5;
+ }
+
+ /* Now the return type is on the top of the stack. */
+
+ s = (char *) xmalloc (len);
+ if (! domain)
+ *s = '\0';
+ else
+ strcpy (s, domain_type);
+ strcat (s, "::| (");
+
+ if (argcount < 0)
+ strcat (s, "/* unknown */");
+ else
+ {
+ int i;
+
+ for (i = 0; i < argcount; i++)
+ {
+ if (i > 0)
+ strcat (s, ", ");
+ strcat (s, arg_types[i]);
+ }
+ if (varargs)
+ {
+ if (i > 0)
+ strcat (s, ", ");
+ strcat (s, "...");
+ }
+ if (argcount > 0)
+ free (arg_types);
+ }
+
+ strcat (s, ")");
+
+ if (! substitute_type (info, s))
+ return false;
+
+ free (s);
+
+ return true;
+}
+
+/* Make a const qualified type. */
+
+static boolean
+pr_const_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ return substitute_type (info, "const |");
+}
+
+/* Make a volatile qualified type. */
+
+static boolean
+pr_volatile_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ return substitute_type (info, "volatile |");
+}
+
+/* Start accumulating a struct type. */
+
+static boolean
+pr_start_struct_type (p, tag, id, structp, size)
+ PTR p;
+ const char *tag;
+ unsigned int id;
+ boolean structp;
+ unsigned int size;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ info->indent += 2;
+
+ if (! push_type (info, structp ? "struct " : "union "))
+ return false;
+ if (tag != NULL)
+ {
+ if (! append_type (info, tag))
+ return false;
+ }
+ else
+ {
+ char idbuf[20];
+
+ sprintf (idbuf, "%%anon%u", id);
+ if (! append_type (info, idbuf))
+ return false;
+ }
+
+ if (! append_type (info, " {"))
+ return false;
+ if (size != 0 || tag != NULL)
+ {
+ char ab[30];
+
+ if (! append_type (info, " /*"))
+ return false;
+
+ if (size != 0)
+ {
+ sprintf (ab, " size %u", size);
+ if (! append_type (info, ab))
+ return false;
+ }
+ if (tag != NULL)
+ {
+ sprintf (ab, " id %u", id);
+ if (! append_type (info, ab))
+ return false;
+ }
+ if (! append_type (info, " */"))
+ return false;
+ }
+ if (! append_type (info, "\n"))
+ return false;
+
+ info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
+
+ return indent_type (info);
+}
+
+/* Output the visibility of a field in a struct. */
+
+static boolean
+pr_fix_visibility (info, visibility)
+ struct pr_handle *info;
+ enum debug_visibility visibility;
+{
+ const char *s;
+ char *t;
+ unsigned int len;
+
+ assert (info->stack != NULL);
+
+ if (info->stack->visibility == visibility)
+ return true;
+
+ assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE);
+
+ switch (visibility)
+ {
+ case DEBUG_VISIBILITY_PUBLIC:
+ s = "public";
+ break;
+ case DEBUG_VISIBILITY_PRIVATE:
+ s = "private";
+ break;
+ case DEBUG_VISIBILITY_PROTECTED:
+ s = "protected";
+ break;
+ default:
+ abort ();
+ return false;
+ }
+
+ /* Trim off a trailing space in the struct string, to make the
+ output look a bit better, then stick on the visibility string. */
+
+ t = info->stack->type;
+ len = strlen (t);
+ assert (t[len - 1] == ' ');
+ t[len - 1] = '\0';
+
+ if (! append_type (info, s)
+ || ! append_type (info, ":\n")
+ || ! indent_type (info))
+ return false;
+
+ info->stack->visibility = visibility;
+
+ return true;
+}
+
+/* Add a field to a struct type. */
+
+static boolean
+pr_struct_field (p, name, bitpos, bitsize, visibility)
+ PTR p;
+ const char *name;
+ bfd_vma bitpos;
+ bfd_vma bitsize;
+ enum debug_visibility visibility;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[20];
+ char *t;
+
+ if (! substitute_type (info, name))
+ return false;
+
+ if (! append_type (info, "; /* "))
+ return false;
+
+ if (bitsize != 0)
+ {
+ print_vma (bitsize, ab, true, false);
+ if (! append_type (info, "bitsize ")
+ || ! append_type (info, ab)
+ || ! append_type (info, ", "))
+ return false;
+ }
+
+ print_vma (bitpos, ab, true, false);
+ if (! append_type (info, "bitpos ")
+ || ! append_type (info, ab)
+ || ! append_type (info, " */\n")
+ || ! indent_type (info))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ if (! pr_fix_visibility (info, visibility))
+ return false;
+
+ return append_type (info, t);
+}
+
+/* Finish a struct type. */
+
+static boolean
+pr_end_struct_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *s;
+
+ assert (info->stack != NULL);
+ assert (info->indent >= 2);
+
+ info->indent -= 2;
+
+ /* Change the trailing indentation to have a close brace. */
+ s = info->stack->type + strlen (info->stack->type) - 2;
+ assert (strcmp (s, " ") == 0);
+
+ *s++ = '}';
+ *s = '\0';
+
+ return true;
+}
+
+/* Start a class type. */
+
+static boolean
+pr_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
+ PTR p;
+ const char *tag;
+ unsigned int id;
+ boolean structp;
+ unsigned int size;
+ boolean vptr;
+ boolean ownvptr;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *tv = NULL;
+
+ info->indent += 2;
+
+ if (vptr && ! ownvptr)
+ {
+ tv = pop_type (info);
+ if (tv == NULL)
+ return false;
+ }
+
+ if (! push_type (info, structp ? "class " : "union class "))
+ return false;
+ if (tag != NULL)
+ {
+ if (! append_type (info, tag))
+ return false;
+ }
+ else
+ {
+ char idbuf[20];
+
+ sprintf (idbuf, "%%anon%u", id);
+ if (! append_type (info, idbuf))
+ return false;
+ }
+
+ if (! append_type (info, " {"))
+ return false;
+ if (size != 0 || vptr || ownvptr || tag != NULL)
+ {
+ if (! append_type (info, " /*"))
+ return false;
+
+ if (size != 0)
+ {
+ char ab[20];
+
+ sprintf (ab, "%u", size);
+ if (! append_type (info, " size ")
+ || ! append_type (info, ab))
+ return false;
+ }
+
+ if (vptr)
+ {
+ if (! append_type (info, " vtable "))
+ return false;
+ if (ownvptr)
+ {
+ if (! append_type (info, "self "))
+ return false;
+ }
+ else
+ {
+ if (! append_type (info, tv)
+ || ! append_type (info, " "))
+ return false;
+ }
+ }
+
+ if (tag != NULL)
+ {
+ char ab[30];
+
+ sprintf (ab, " id %u", id);
+ if (! append_type (info, ab))
+ return false;
+ }
+
+ if (! append_type (info, " */"))
+ return false;
+ }
+
+ info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
+
+ return (append_type (info, "\n")
+ && indent_type (info));
+}
+
+/* Add a static member to a class. */
+
+static boolean
+pr_class_static_member (p, name, physname, visibility)
+ PTR p;
+ const char *name;
+ const char *physname;
+ enum debug_visibility visibility;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+
+ if (! substitute_type (info, name))
+ return false;
+
+ if (! prepend_type (info, "static ")
+ || ! append_type (info, "; /* ")
+ || ! append_type (info, physname)
+ || ! append_type (info, " */\n")
+ || ! indent_type (info))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ if (! pr_fix_visibility (info, visibility))
+ return false;
+
+ return append_type (info, t);
+}
+
+/* Add a base class to a class. */
+
+static boolean
+pr_class_baseclass (p, bitpos, virtual, visibility)
+ PTR p;
+ bfd_vma bitpos;
+ boolean virtual;
+ enum debug_visibility visibility;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+ const char *prefix;
+ char ab[20];
+ char *s, *l, *n;
+
+ assert (info->stack != NULL && info->stack->next != NULL);
+
+ if (! substitute_type (info, ""))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ if (strncmp (t, "class ", sizeof "class " - 1) == 0)
+ t += sizeof "class " - 1;
+
+ /* Push it back on to take advantage of the prepend_type and
+ append_type routines. */
+ if (! push_type (info, t))
+ return false;
+
+ if (virtual)
+ {
+ if (! prepend_type (info, "virtual "))
+ return false;
+ }
+
+ switch (visibility)
+ {
+ case DEBUG_VISIBILITY_PUBLIC:
+ prefix = "public ";
+ break;
+ case DEBUG_VISIBILITY_PROTECTED:
+ prefix = "protected ";
+ break;
+ case DEBUG_VISIBILITY_PRIVATE:
+ prefix = "private ";
+ break;
+ default:
+ prefix = "/* unknown visibility */ ";
+ break;
+ }
+
+ if (! prepend_type (info, prefix))
+ return false;
+
+ if (bitpos != 0)
+ {
+ print_vma (bitpos, ab, true, false);
+ if (! append_type (info, " /* bitpos ")
+ || ! append_type (info, ab)
+ || ! append_type (info, " */"))
+ return false;
+ }
+
+ /* Now the top of the stack is something like "public A / * bitpos
+ 10 * /". The next element on the stack is something like "class
+ xx { / * size 8 * /\n...". We want to substitute the top of the
+ stack in before the {. */
+ s = strchr (info->stack->next->type, '{');
+ assert (s != NULL);
+ --s;
+
+ /* If there is already a ':', then we already have a baseclass, and
+ we must append this one after a comma. */
+ for (l = info->stack->next->type; l != s; l++)
+ if (*l == ':')
+ break;
+ if (! prepend_type (info, l == s ? " : " : ", "))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1);
+ memcpy (n, info->stack->type, s - info->stack->type);
+ strcpy (n + (s - info->stack->type), t);
+ strcat (n, s);
+
+ free (info->stack->type);
+ info->stack->type = n;
+
+ free (t);
+
+ return true;
+}
+
+/* Start adding a method to a class. */
+
+static boolean
+pr_class_start_method (p, name)
+ PTR p;
+ const char *name;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ assert (info->stack != NULL);
+ info->stack->method = name;
+ return true;
+}
+
+/* Add a variant to a method. */
+
+static boolean
+pr_class_method_variant (p, physname, visibility, constp, volatilep, voffset,
+ context)
+ PTR p;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ boolean context;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *method_type;
+ char *context_type;
+
+ assert (info->stack != NULL);
+ assert (info->stack->next != NULL);
+
+ /* Put the const and volatile qualifiers on the type. */
+ if (volatilep)
+ {
+ if (! append_type (info, " volatile"))
+ return false;
+ }
+ if (constp)
+ {
+ if (! append_type (info, " const"))
+ return false;
+ }
+
+ /* Stick the name of the method into its type. */
+ if (! substitute_type (info,
+ (context
+ ? info->stack->next->next->method
+ : info->stack->next->method)))
+ return false;
+
+ /* Get the type. */
+ method_type = pop_type (info);
+ if (method_type == NULL)
+ return false;
+
+ /* Pull off the context type if there is one. */
+ if (! context)
+ context_type = NULL;
+ else
+ {
+ context_type = pop_type (info);
+ if (context_type == NULL)
+ return false;
+ }
+
+ /* Now the top of the stack is the class. */
+
+ if (! pr_fix_visibility (info, visibility))
+ return false;
+
+ if (! append_type (info, method_type)
+ || ! append_type (info, " /* ")
+ || ! append_type (info, physname)
+ || ! append_type (info, " "))
+ return false;
+ if (context || voffset != 0)
+ {
+ char ab[20];
+
+ if (context)
+ {
+ if (! append_type (info, "context ")
+ || ! append_type (info, context_type)
+ || ! append_type (info, " "))
+ return false;
+ }
+ print_vma (voffset, ab, true, false);
+ if (! append_type (info, "voffset ")
+ || ! append_type (info, ab))
+ return false;
+ }
+
+ return (append_type (info, " */;\n")
+ && indent_type (info));
+}
+
+/* Add a static variant to a method. */
+
+static boolean
+pr_class_static_method_variant (p, physname, visibility, constp, volatilep)
+ PTR p;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *method_type;
+
+ assert (info->stack != NULL);
+ assert (info->stack->next != NULL);
+ assert (info->stack->next->method != NULL);
+
+ /* Put the const and volatile qualifiers on the type. */
+ if (volatilep)
+ {
+ if (! append_type (info, " volatile"))
+ return false;
+ }
+ if (constp)
+ {
+ if (! append_type (info, " const"))
+ return false;
+ }
+
+ /* Mark it as static. */
+ if (! prepend_type (info, "static "))
+ return false;
+
+ /* Stick the name of the method into its type. */
+ if (! substitute_type (info, info->stack->next->method))
+ return false;
+
+ /* Get the type. */
+ method_type = pop_type (info);
+ if (method_type == NULL)
+ return false;
+
+ /* Now the top of the stack is the class. */
+
+ if (! pr_fix_visibility (info, visibility))
+ return false;
+
+ return (append_type (info, method_type)
+ && append_type (info, " /* ")
+ && append_type (info, physname)
+ && append_type (info, " */;\n")
+ && indent_type (info));
+}
+
+/* Finish up a method. */
+
+static boolean
+pr_class_end_method (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ info->stack->method = NULL;
+ return true;
+}
+
+/* Finish up a class. */
+
+static boolean
+pr_end_class_type (p)
+ PTR p;
+{
+ return pr_end_struct_type (p);
+}
+
+/* Push a type on the stack using a typedef name. */
+
+static boolean
+pr_typedef_type (p, name)
+ PTR p;
+ const char *name;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ return push_type (info, name);
+}
+
+/* Push a type on the stack using a tag name. */
+
+static boolean
+pr_tag_type (p, name, id, kind)
+ PTR p;
+ const char *name;
+ unsigned int id;
+ enum debug_type_kind kind;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ const char *t, *tag;
+ char idbuf[20];
+
+ switch (kind)
+ {
+ case DEBUG_KIND_STRUCT:
+ t = "struct ";
+ break;
+ case DEBUG_KIND_UNION:
+ t = "union ";
+ break;
+ case DEBUG_KIND_ENUM:
+ t = "enum ";
+ break;
+ case DEBUG_KIND_CLASS:
+ t = "class ";
+ break;
+ case DEBUG_KIND_UNION_CLASS:
+ t = "union class ";
+ break;
+ default:
+ abort ();
+ return false;
+ }
+
+ if (! push_type (info, t))
+ return false;
+ if (name != NULL)
+ tag = name;
+ else
+ {
+ sprintf (idbuf, "%%anon%u", id);
+ tag = idbuf;
+ }
+
+ if (! append_type (info, tag))
+ return false;
+ if (name != NULL && kind != DEBUG_KIND_ENUM)
+ {
+ sprintf (idbuf, " /* id %u */", id);
+ if (! append_type (info, idbuf))
+ return false;
+ }
+
+ return true;
+}
+
+/* Output a typedef. */
+
+static boolean
+pr_typdef (p, name)
+ PTR p;
+ const char *name;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *s;
+
+ if (! substitute_type (info, name))
+ return false;
+
+ s = pop_type (info);
+ if (s == NULL)
+ return false;
+
+ indent (info);
+ fprintf (info->f, "typedef %s;\n", s);
+
+ free (s);
+
+ return true;
+}
+
+/* Output a tag. The tag should already be in the string on the
+ stack, so all we have to do here is print it out. */
+
+/*ARGSUSED*/
+static boolean
+pr_tag (p, name)
+ PTR p;
+ const char *name;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ indent (info);
+ fprintf (info->f, "%s;\n", t);
+
+ free (t);
+
+ return true;
+}
+
+/* Output an integer constant. */
+
+static boolean
+pr_int_constant (p, name, val)
+ PTR p;
+ const char *name;
+ bfd_vma val;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[20];
+
+ indent (info);
+ print_vma (val, ab, false, false);
+ fprintf (info->f, "const int %s = %s;\n", name, ab);
+ return true;
+}
+
+/* Output a floating point constant. */
+
+static boolean
+pr_float_constant (p, name, val)
+ PTR p;
+ const char *name;
+ double val;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ indent (info);
+ fprintf (info->f, "const double %s = %g;\n", name, val);
+ return true;
+}
+
+/* Output a typed constant. */
+
+static boolean
+pr_typed_constant (p, name, val)
+ PTR p;
+ const char *name;
+ bfd_vma val;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+ char ab[20];
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ indent (info);
+ print_vma (val, ab, false, false);
+ fprintf (info->f, "const %s %s = %s;\n", t, name, ab);
+
+ free (t);
+
+ return true;
+}
+
+/* Output a variable. */
+
+static boolean
+pr_variable (p, name, kind, val)
+ PTR p;
+ const char *name;
+ enum debug_var_kind kind;
+ bfd_vma val;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+ char ab[20];
+
+ if (! substitute_type (info, name))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ indent (info);
+ switch (kind)
+ {
+ case DEBUG_STATIC:
+ case DEBUG_LOCAL_STATIC:
+ fprintf (info->f, "static ");
+ break;
+ case DEBUG_REGISTER:
+ fprintf (info->f, "register ");
+ break;
+ default:
+ break;
+ }
+ print_vma (val, ab, true, true);
+ fprintf (info->f, "%s /* %s */;\n", t, ab);
+
+ free (t);
+
+ return true;
+}
+
+/* Start outputting a function. */
+
+static boolean
+pr_start_function (p, name, global)
+ PTR p;
+ const char *name;
+ boolean global;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+
+ if (! substitute_type (info, name))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ indent (info);
+ if (! global)
+ fprintf (info->f, "static ");
+ fprintf (info->f, "%s (", t);
+
+ info->parameter = 1;
+
+ return true;
+}
+
+/* Output a function parameter. */
+
+static boolean
+pr_function_parameter (p, name, kind, val)
+ PTR p;
+ const char *name;
+ enum debug_parm_kind kind;
+ bfd_vma val;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+ char ab[20];
+
+ if (kind == DEBUG_PARM_REFERENCE
+ || kind == DEBUG_PARM_REF_REG)
+ {
+ if (! pr_reference_type (p))
+ return false;
+ }
+
+ if (! substitute_type (info, name))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ if (info->parameter != 1)
+ fprintf (info->f, ", ");
+
+ if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
+ fprintf (info->f, "register ");
+
+ print_vma (val, ab, true, true);
+ fprintf (info->f, "%s /* %s */", t, ab);
+
+ free (t);
+
+ ++info->parameter;
+
+ return true;
+}
+
+/* Start writing out a block. */
+
+static boolean
+pr_start_block (p, addr)
+ PTR p;
+ bfd_vma addr;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[20];
+
+ if (info->parameter > 0)
+ {
+ fprintf (info->f, ")\n");
+ info->parameter = 0;
+ }
+
+ indent (info);
+ print_vma (addr, ab, true, true);
+ fprintf (info->f, "{ /* %s */\n", ab);
+
+ info->indent += 2;
+
+ return true;
+}
+
+/* Write out line number information. */
+
+static boolean
+pr_lineno (p, filename, lineno, addr)
+ PTR p;
+ const char *filename;
+ unsigned long lineno;
+ bfd_vma addr;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[20];
+
+ indent (info);
+ print_vma (addr, ab, true, true);
+ fprintf (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab);
+
+ return true;
+}
+
+/* Finish writing out a block. */
+
+static boolean
+pr_end_block (p, addr)
+ PTR p;
+ bfd_vma addr;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[20];
+
+ info->indent -= 2;
+
+ indent (info);
+ print_vma (addr, ab, true, true);
+ fprintf (info->f, "} /* %s */\n", ab);
+
+ return true;
+}
+
+/* Finish writing out a function. */
+
+/*ARGSUSED*/
+static boolean
+pr_end_function (p)
+ PTR p;
+{
+ return true;
+}
diff --git a/gnu/usr.bin/binutils/binutils/rdcoff.c b/gnu/usr.bin/binutils/binutils/rdcoff.c
new file mode 100644
index 00000000000..9f7660b278e
--- /dev/null
+++ b/gnu/usr.bin/binutils/binutils/rdcoff.c
@@ -0,0 +1,874 @@
+/* stabs.c -- Parse COFF debugging information
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ 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. */
+
+/* This file contains code which parses COFF debugging information. */
+
+#include "bfd.h"
+#include "coff/internal.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "demangle.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* FIXME: We should not need this BFD internal file. We need it for
+ the N_BTMASK, etc., values. */
+#include "libcoff.h"
+
+/* These macros extract the right mask and shifts for this BFD. They
+ assume that there is a local variable named ABFD. This is so that
+ macros like ISFCN and DECREF, from coff/internal.h, will work
+ without modification. */
+#define N_BTMASK (coff_data (abfd)->local_n_btmask)
+#define N_BTSHFT (coff_data (abfd)->local_n_btshft)
+#define N_TMASK (coff_data (abfd)->local_n_tmask)
+#define N_TSHIFT (coff_data (abfd)->local_n_tshift)
+
+/* This structure is used to hold the symbols, as well as the current
+ location within the symbols. */
+
+struct coff_symbols
+{
+ /* The symbols. */
+ asymbol **syms;
+ /* The number of symbols. */
+ long symcount;
+ /* The index of the current symbol. */
+ long symno;
+ /* The index of the current symbol in the COFF symbol table (where
+ each auxent counts as a symbol). */
+ long coff_symno;
+};
+
+/* The largest basic type we are prepared to handle. */
+
+#define T_MAX (T_LNGDBL)
+
+/* This structure is used to hold slots. */
+
+struct coff_slots
+{
+ /* Next set of slots. */
+ struct coff_slots *next;
+ /* Slots. */
+#define COFF_SLOTS (16)
+ debug_type slots[COFF_SLOTS];
+};
+
+/* This structure is used to map symbol indices to types. */
+
+struct coff_types
+{
+ /* Slots. */
+ struct coff_slots *slots;
+ /* Basic types. */
+ debug_type basic[T_MAX + 1];
+};
+
+static debug_type *coff_get_slot PARAMS ((struct coff_types *, int));
+static debug_type parse_coff_type
+ PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, long, int,
+ union internal_auxent *, boolean, PTR));
+static debug_type parse_coff_base_type
+ PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, long, int,
+ union internal_auxent *, PTR));
+static debug_type parse_coff_struct_type
+ PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, int,
+ union internal_auxent *, PTR));
+static debug_type parse_coff_enum_type
+ PARAMS ((bfd *, struct coff_symbols *, struct coff_types *,
+ union internal_auxent *, PTR));
+static boolean parse_coff_symbol
+ PARAMS ((bfd *, struct coff_types *, asymbol *, long,
+ struct internal_syment *, PTR, debug_type, boolean));
+
+/* Return the slot for a type. */
+
+static debug_type *
+coff_get_slot (types, indx)
+ struct coff_types *types;
+ int indx;
+{
+ struct coff_slots **pps;
+
+ pps = &types->slots;
+
+ while (indx >= COFF_SLOTS)
+ {
+ if (*pps == NULL)
+ {
+ *pps = (struct coff_slots *) xmalloc (sizeof **pps);
+ memset (*pps, 0, sizeof **pps);
+ }
+ pps = &(*pps)->next;
+ indx -= COFF_SLOTS;
+ }
+
+ if (*pps == NULL)
+ {
+ *pps = (struct coff_slots *) xmalloc (sizeof **pps);
+ memset (*pps, 0, sizeof **pps);
+ }
+
+ return (*pps)->slots + indx;
+}
+
+/* Parse a COFF type code in NTYPE. */
+
+static debug_type
+parse_coff_type (abfd, symbols, types, coff_symno, ntype, pauxent, useaux,
+ dhandle)
+ bfd *abfd;
+ struct coff_symbols *symbols;
+ struct coff_types *types;
+ long coff_symno;
+ int ntype;
+ union internal_auxent *pauxent;
+ boolean useaux;
+ PTR dhandle;
+{
+ debug_type type;
+
+ if ((ntype & ~N_BTMASK) != 0)
+ {
+ int newtype;
+
+ newtype = DECREF (ntype);
+
+ if (ISPTR (ntype))
+ {
+ type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
+ pauxent, useaux, dhandle);
+ type = debug_make_pointer_type (dhandle, type);
+ }
+ else if (ISFCN (ntype))
+ {
+ type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
+ pauxent, useaux, dhandle);
+ type = debug_make_function_type (dhandle, type, (debug_type *) NULL,
+ false);
+ }
+ else if (ISARY (ntype))
+ {
+ int n;
+
+ if (pauxent == NULL)
+ n = 0;
+ else
+ {
+ unsigned short *dim;
+ int i;
+
+ /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets
+ the c_naux field of the syment to 0. */
+
+ /* Move the dimensions down, so that the next array
+ picks up the next one. */
+ dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen;
+ n = dim[0];
+ for (i = 0; *dim != 0 && i < DIMNUM - 1; i++, dim++)
+ *dim = *(dim + 1);
+ *dim = 0;
+ }
+
+ type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
+ pauxent, false, dhandle);
+ type = debug_make_array_type (dhandle, type,
+ parse_coff_base_type (abfd, symbols,
+ types,
+ coff_symno,
+ T_INT,
+ NULL, dhandle),
+ 0, n - 1, false);
+ }
+
+ return type;
+ }
+
+ if (pauxent != NULL && pauxent->x_sym.x_tagndx.l > 0)
+ {
+ debug_type *slot;
+
+ /* This is a reference to an existing type. FIXME: gdb checks
+ that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG. */
+ slot = coff_get_slot (types, pauxent->x_sym.x_tagndx.l);
+ if (*slot != DEBUG_TYPE_NULL)
+ return *slot;
+ else
+ return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
+ }
+
+ /* If the aux entry has already been used for something, useaux will
+ have been set to false, indicating that parse_coff_base_type
+ should not use it. We need to do it this way, rather than simply
+ passing pauxent as NULL, because we need to be able handle
+ multiple array dimensions while still discarding pauxent after
+ having handled all of them. */
+ if (! useaux)
+ pauxent = NULL;
+
+ return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype,
+ pauxent, dhandle);
+}
+
+/* Parse a basic COFF type in NTYPE. */
+
+static debug_type
+parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent,
+ dhandle)
+ bfd *abfd;
+ struct coff_symbols *symbols;
+ struct coff_types *types;
+ long coff_symno;
+ int ntype;
+ union internal_auxent *pauxent;
+ PTR dhandle;
+{
+ debug_type ret;
+ boolean set_basic;
+ const char *name;
+ debug_type *slot;
+
+ if (ntype >= 0
+ && ntype <= T_MAX
+ && types->basic[ntype] != DEBUG_TYPE_NULL)
+ return types->basic[ntype];
+
+ set_basic = true;
+ name = NULL;
+
+ switch (ntype)
+ {
+ default:
+ ret = debug_make_void_type (dhandle);
+ break;
+
+ case T_NULL:
+ case T_VOID:
+ ret = debug_make_void_type (dhandle);
+ name = "void";
+ break;
+
+ case T_CHAR:
+ ret = debug_make_int_type (dhandle, 1, false);
+ name = "char";
+ break;
+
+ case T_SHORT:
+ ret = debug_make_int_type (dhandle, 2, false);
+ name = "short";
+ break;
+
+ case T_INT:
+ /* FIXME: Perhaps the size should depend upon the architecture. */
+ ret = debug_make_int_type (dhandle, 4, false);
+ name = "int";
+ break;
+
+ case T_LONG:
+ ret = debug_make_int_type (dhandle, 4, false);
+ name = "long";
+ break;
+
+ case T_FLOAT:
+ ret = debug_make_float_type (dhandle, 4);
+ name = "float";
+ break;
+
+ case T_DOUBLE:
+ ret = debug_make_float_type (dhandle, 8);
+ name = "double";
+ break;
+
+ case T_LNGDBL:
+ ret = debug_make_float_type (dhandle, 12);
+ name = "long double";
+ break;
+
+ case T_UCHAR:
+ ret = debug_make_int_type (dhandle, 1, true);
+ name = "unsigned char";
+ break;
+
+ case T_USHORT:
+ ret = debug_make_int_type (dhandle, 2, true);
+ name = "unsigned short";
+ break;
+
+ case T_UINT:
+ ret = debug_make_int_type (dhandle, 4, true);
+ name = "unsigned int";
+ break;
+
+ case T_ULONG:
+ ret = debug_make_int_type (dhandle, 4, true);
+ name = "unsigned long";
+ break;
+
+ case T_STRUCT:
+ if (pauxent == NULL)
+ ret = debug_make_struct_type (dhandle, true, 0,
+ (debug_field *) NULL);
+ else
+ ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
+ dhandle);
+
+ slot = coff_get_slot (types, coff_symno);
+ *slot = ret;
+
+ set_basic = false;
+ break;
+
+ case T_UNION:
+ if (pauxent == NULL)
+ ret = debug_make_struct_type (dhandle, false, 0, (debug_field *) NULL);
+ else
+ ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
+ dhandle);
+
+ slot = coff_get_slot (types, coff_symno);
+ *slot = ret;
+
+ set_basic = false;
+ break;
+
+ case T_ENUM:
+ if (pauxent == NULL)
+ ret = debug_make_enum_type (dhandle, (const char **) NULL,
+ (bfd_signed_vma *) NULL);
+ else
+ ret = parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle);
+
+ slot = coff_get_slot (types, coff_symno);
+ *slot = ret;
+
+ set_basic = false;
+ break;
+ }
+
+ if (name != NULL)
+ ret = debug_name_type (dhandle, name, ret);
+
+ if (set_basic
+ && ntype >= 0
+ && ntype <= T_MAX)
+ types->basic[ntype] = ret;
+
+ return ret;
+}
+
+/* Parse a struct type. */
+
+static debug_type
+parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle)
+ bfd *abfd;
+ struct coff_symbols *symbols;
+ struct coff_types *types;
+ int ntype;
+ union internal_auxent *pauxent;
+ PTR dhandle;
+{
+ long symend;
+ int alloc;
+ debug_field *fields;
+ int count;
+ boolean done;
+
+ symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
+
+ alloc = 10;
+ fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+ count = 0;
+
+ done = false;
+ while (! done
+ && symbols->coff_symno < symend
+ && symbols->symno < symbols->symcount)
+ {
+ asymbol *sym;
+ long this_coff_symno;
+ struct internal_syment syment;
+ union internal_auxent auxent;
+ union internal_auxent *psubaux;
+ bfd_vma bitpos = 0, bitsize = 0;
+
+ sym = symbols->syms[symbols->symno];
+
+ if (! bfd_coff_get_syment (abfd, sym, &syment))
+ {
+ fprintf (stderr, "%s: bfd_coff_get_syment failed: %s\n",
+ program_name, bfd_errmsg (bfd_get_error ()));
+ return DEBUG_TYPE_NULL;
+ }
+
+ this_coff_symno = symbols->coff_symno;
+
+ ++symbols->symno;
+ symbols->coff_symno += 1 + syment.n_numaux;
+
+ if (syment.n_numaux == 0)
+ psubaux = NULL;
+ else
+ {
+ if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
+ {
+ fprintf (stderr, "%s: bfd_coff_get_auxent failed: %s\n",
+ program_name, bfd_errmsg (bfd_get_error ()));
+ return DEBUG_TYPE_NULL;
+ }
+ psubaux = &auxent;
+ }
+
+ switch (syment.n_sclass)
+ {
+ case C_MOS:
+ case C_MOU:
+ bitpos = 8 * bfd_asymbol_value (sym);
+ bitsize = 0;
+ break;
+
+ case C_FIELD:
+ bitpos = bfd_asymbol_value (sym);
+ bitsize = auxent.x_sym.x_misc.x_lnsz.x_size;
+ break;
+
+ case C_EOS:
+ done = true;
+ break;
+ }
+
+ if (! done)
+ {
+ debug_type ftype;
+ debug_field f;
+
+ ftype = parse_coff_type (abfd, symbols, types, this_coff_symno,
+ syment.n_type, psubaux, true, dhandle);
+ f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype,
+ bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC);
+ if (f == DEBUG_FIELD_NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (count + 1 >= alloc)
+ {
+ alloc += 10;
+ fields = ((debug_field *)
+ xrealloc (fields, alloc * sizeof *fields));
+ }
+
+ fields[count] = f;
+ ++count;
+ }
+ }
+
+ fields[count] = DEBUG_FIELD_NULL;
+
+ return debug_make_struct_type (dhandle, ntype == T_STRUCT,
+ pauxent->x_sym.x_misc.x_lnsz.x_size,
+ fields);
+}
+
+/* Parse an enum type. */
+
+static debug_type
+parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle)
+ bfd *abfd;
+ struct coff_symbols *symbols;
+ struct coff_types *types;
+ union internal_auxent *pauxent;
+ PTR dhandle;
+{
+ long symend;
+ int alloc;
+ const char **names;
+ bfd_signed_vma *vals;
+ int count;
+ boolean done;
+
+ symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
+
+ alloc = 10;
+ names = (const char **) xmalloc (alloc * sizeof *names);
+ vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *vals);
+ count = 0;
+
+ done = false;
+ while (! done
+ && symbols->coff_symno < symend
+ && symbols->symno < symbols->symcount)
+ {
+ asymbol *sym;
+ struct internal_syment syment;
+
+ sym = symbols->syms[symbols->symno];
+
+ if (! bfd_coff_get_syment (abfd, sym, &syment))
+ {
+ fprintf (stderr, "%s: bfd_coff_get_syment failed: %s\n",
+ program_name, bfd_errmsg (bfd_get_error ()));
+ return DEBUG_TYPE_NULL;
+ }
+
+ ++symbols->symno;
+ symbols->coff_symno += 1 + syment.n_numaux;
+
+ switch (syment.n_sclass)
+ {
+ case C_MOE:
+ if (count + 1 >= alloc)
+ {
+ alloc += 10;
+ names = ((const char **)
+ xrealloc (names, alloc * sizeof *names));
+ vals = ((bfd_signed_vma *)
+ xrealloc (vals, alloc * sizeof *vals));
+ }
+
+ names[count] = bfd_asymbol_name (sym);
+ vals[count] = bfd_asymbol_value (sym);
+ ++count;
+ break;
+
+ case C_EOS:
+ done = true;
+ break;
+ }
+ }
+
+ names[count] = NULL;
+
+ return debug_make_enum_type (dhandle, names, vals);
+}
+
+/* Handle a single COFF symbol. */
+
+static boolean
+parse_coff_symbol (abfd, types, sym, coff_symno, psyment, dhandle, type,
+ within_function)
+ bfd *abfd;
+ struct coff_types *types;
+ asymbol *sym;
+ long coff_symno;
+ struct internal_syment *psyment;
+ PTR dhandle;
+ debug_type type;
+ boolean within_function;
+{
+ switch (psyment->n_sclass)
+ {
+ case C_NULL:
+ break;
+
+ case C_AUTO:
+ if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
+ DEBUG_LOCAL, bfd_asymbol_value (sym)))
+ return false;
+ break;
+
+ case C_EXT:
+ if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
+ DEBUG_GLOBAL, bfd_asymbol_value (sym)))
+ return false;
+ break;
+
+ case C_STAT:
+ if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
+ (within_function
+ ? DEBUG_LOCAL_STATIC
+ : DEBUG_STATIC),
+ bfd_asymbol_value (sym)))
+ return false;
+ break;
+
+ case C_REG:
+ /* FIXME: We may need to convert the register number. */
+ if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
+ DEBUG_REGISTER, bfd_asymbol_value (sym)))
+ return false;
+ break;
+
+ case C_LABEL:
+ break;
+
+ case C_ARG:
+ if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
+ DEBUG_PARM_STACK, bfd_asymbol_value (sym)))
+ return false;
+ break;
+
+ case C_REGPARM:
+ /* FIXME: We may need to convert the register number. */
+ if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
+ DEBUG_PARM_REG, bfd_asymbol_value (sym)))
+ return false;
+ break;
+
+ case C_TPDEF:
+ type = debug_name_type (dhandle, bfd_asymbol_name (sym), type);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+ break;
+
+ case C_STRTAG:
+ case C_UNTAG:
+ case C_ENTAG:
+ {
+ debug_type *slot;
+
+ type = debug_tag_type (dhandle, bfd_asymbol_name (sym), type);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ /* Store the named type into the slot, so that references get
+ the name. */
+ slot = coff_get_slot (types, coff_symno);
+ *slot = type;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+/* This is the main routine. It looks through all the symbols and
+ handles them. */
+
+boolean
+parse_coff (abfd, syms, symcount, dhandle)
+ bfd *abfd;
+ asymbol **syms;
+ long symcount;
+ PTR dhandle;
+{
+ struct coff_symbols symbols;
+ struct coff_types types;
+ int i;
+ long next_c_file;
+ const char *fnname;
+ int fnclass;
+ int fntype;
+ alent *linenos;
+ boolean within_function;
+ long this_coff_symno;
+
+ symbols.syms = syms;
+ symbols.symcount = symcount;
+ symbols.symno = 0;
+ symbols.coff_symno = 0;
+
+ types.slots = NULL;
+ for (i = 0; i <= T_MAX; i++)
+ types.basic[i] = DEBUG_TYPE_NULL;
+
+ next_c_file = -1;
+ fnname = NULL;
+ fnclass = 0;
+ fntype = 0;
+ linenos = NULL;
+ within_function = false;
+
+ while (symbols.symno < symcount)
+ {
+ asymbol *sym;
+ const char *name;
+ struct internal_syment syment;
+ union internal_auxent auxent;
+ union internal_auxent *paux;
+ debug_type type;
+
+ sym = syms[symbols.symno];
+
+ if (! bfd_coff_get_syment (abfd, sym, &syment))
+ {
+ fprintf (stderr, "%s: bfd_coff_get_syment failed: %s\n",
+ program_name, bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+
+ name = bfd_asymbol_name (sym);
+
+ this_coff_symno = symbols.coff_symno;
+
+ ++symbols.symno;
+ symbols.coff_symno += 1 + syment.n_numaux;
+
+ /* We only worry about the first auxent, because that is the
+ only one which is relevant for debugging information. */
+ if (syment.n_numaux == 0)
+ paux = NULL;
+ else
+ {
+ if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
+ {
+ fprintf (stderr, "%s: bfd_coff_get_auxent failed: %s\n",
+ program_name, bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+ paux = &auxent;
+ }
+
+ if (this_coff_symno == next_c_file && syment.n_sclass != C_FILE)
+ {
+ /* The last C_FILE symbol points to the first external
+ symbol. */
+ if (! debug_set_filename (dhandle, "*globals*"))
+ return false;
+ }
+
+ switch (syment.n_sclass)
+ {
+ case C_EFCN:
+ case C_EXTDEF:
+ case C_ULABEL:
+ case C_USTATIC:
+ case C_LINE:
+ case C_ALIAS:
+ case C_HIDDEN:
+ /* Just ignore these classes. */
+ break;
+
+ case C_FILE:
+ next_c_file = syment.n_value;
+ if (! debug_set_filename (dhandle, name))
+ return false;
+ break;
+
+ case C_STAT:
+ /* Ignore static symbols with a type of T_NULL. These
+ represent section entries. */
+ if (syment.n_type == T_NULL)
+ break;
+ /* Fall through. */
+ case C_EXT:
+ if (ISFCN (syment.n_type))
+ {
+ fnname = name;
+ fnclass = syment.n_sclass;
+ fntype = syment.n_type;
+ linenos = BFD_SEND (abfd, _get_lineno, (abfd, sym));
+ break;
+ }
+ type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
+ syment.n_type, paux, true, dhandle);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+ if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
+ dhandle, type, within_function))
+ return false;
+ break;
+
+ case C_FCN:
+ if (strcmp (name, ".bf") == 0)
+ {
+ if (fnname == NULL)
+ {
+ fprintf (stderr, "%s: %ld: .bf without preceding function\n",
+ program_name, this_coff_symno);
+ return false;
+ }
+
+ type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
+ DECREF (fntype), paux, false, dhandle);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ if (! debug_record_function (dhandle, fnname, type,
+ fnclass == C_EXT,
+ bfd_asymbol_value (sym)))
+ return false;
+
+ if (linenos != NULL)
+ {
+ int base;
+ bfd_vma addr;
+
+ if (syment.n_numaux == 0)
+ base = 0;
+ else
+ base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1;
+
+ addr = bfd_get_section_vma (abfd, bfd_get_section (sym));
+
+ ++linenos;
+
+ while (linenos->line_number != 0)
+ {
+ if (! debug_record_line (dhandle,
+ linenos->line_number + base,
+ linenos->u.offset + addr))
+ return false;
+ ++linenos;
+ }
+ }
+
+ fnname = NULL;
+ linenos = NULL;
+ fnclass = 0;
+ fntype = 0;
+
+ within_function = true;
+ }
+ else if (strcmp (name, ".ef") == 0)
+ {
+ if (! within_function)
+ {
+ fprintf (stderr, "%s: %ld: unexpected .ef\n",
+ program_name, this_coff_symno);
+ return false;
+ }
+
+ if (! debug_end_function (dhandle, bfd_asymbol_value (sym)))
+ return false;
+
+ within_function = false;
+ }
+ break;
+
+ case C_BLOCK:
+ if (strcmp (name, ".bb") == 0)
+ {
+ if (! debug_start_block (dhandle, bfd_asymbol_value (sym)))
+ return false;
+ }
+ else if (strcmp (name, ".eb") == 0)
+ {
+ if (! debug_end_block (dhandle, bfd_asymbol_value (sym)))
+ return false;
+ }
+ break;
+
+ default:
+ type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
+ syment.n_type, paux, true, dhandle);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+ if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
+ dhandle, type, within_function))
+ return false;
+ break;
+ }
+ }
+
+ return true;
+}
diff --git a/gnu/usr.bin/binutils/binutils/rddbg.c b/gnu/usr.bin/binutils/binutils/rddbg.c
new file mode 100644
index 00000000000..d14c40df6c3
--- /dev/null
+++ b/gnu/usr.bin/binutils/binutils/rddbg.c
@@ -0,0 +1,432 @@
+/* rddbg.c -- Read debugging information into a generic form.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ 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. */
+
+/* This file reads debugging information into a generic form. This
+ file knows how to dig the debugging information out of an object
+ file. */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "debug.h"
+#include "budbg.h"
+
+static boolean read_section_stabs_debugging_info
+ PARAMS ((bfd *, asymbol **, long, PTR, boolean *));
+static boolean read_symbol_stabs_debugging_info
+ PARAMS ((bfd *, asymbol **, long, PTR, boolean *));
+static boolean read_ieee_debugging_info PARAMS ((bfd *, PTR, boolean *));
+static void save_stab PARAMS ((int, int, bfd_vma, const char *));
+static void stab_context PARAMS ((void));
+static void free_saved_stabs PARAMS ((void));
+
+/* Read debugging information from a BFD. Returns a generic debugging
+ pointer. */
+
+PTR
+read_debugging_info (abfd, syms, symcount)
+ bfd *abfd;
+ asymbol **syms;
+ long symcount;
+{
+ PTR dhandle;
+ boolean found;
+
+ dhandle = debug_init ();
+ if (dhandle == NULL)
+ return NULL;
+
+ if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle,
+ &found))
+ return NULL;
+
+ if (bfd_get_flavour (abfd) == bfd_target_aout_flavour)
+ {
+ if (! read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle,
+ &found))
+ return NULL;
+ }
+
+ if (bfd_get_flavour (abfd) == bfd_target_ieee_flavour)
+ {
+ if (! read_ieee_debugging_info (abfd, dhandle, &found))
+ return NULL;
+ }
+
+ /* Try reading the COFF symbols if we didn't find any stabs in COFF
+ sections. */
+ if (! found
+ && bfd_get_flavour (abfd) == bfd_target_coff_flavour
+ && symcount > 0)
+ {
+ if (! parse_coff (abfd, syms, symcount, dhandle))
+ return NULL;
+ found = true;
+ }
+
+ if (! found)
+ {
+ fprintf (stderr, "%s: no recognized debugging information\n",
+ bfd_get_filename (abfd));
+ return NULL;
+ }
+
+ return dhandle;
+}
+
+/* Read stabs in sections debugging information from a BFD. */
+
+static boolean
+read_section_stabs_debugging_info (abfd, syms, symcount, dhandle, pfound)
+ bfd *abfd;
+ asymbol **syms;
+ long symcount;
+ PTR dhandle;
+ boolean *pfound;
+{
+ static struct
+ {
+ const char *secname;
+ const char *strsecname;
+ } names[] = { { ".stab", ".stabstr" } };
+ unsigned int i;
+ PTR shandle;
+
+ *pfound = false;
+ shandle = NULL;
+
+ for (i = 0; i < sizeof names / sizeof names[0]; i++)
+ {
+ asection *sec, *strsec;
+
+ sec = bfd_get_section_by_name (abfd, names[i].secname);
+ strsec = bfd_get_section_by_name (abfd, names[i].strsecname);
+ if (sec != NULL && strsec != NULL)
+ {
+ bfd_size_type stabsize, strsize;
+ bfd_byte *stabs, *strings;
+ bfd_byte *stab;
+ bfd_size_type stroff, next_stroff;
+
+ stabsize = bfd_section_size (abfd, sec);
+ stabs = (bfd_byte *) xmalloc (stabsize);
+ if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize))
+ {
+ fprintf (stderr, "%s: %s: %s\n",
+ bfd_get_filename (abfd), names[i].secname,
+ bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+
+ strsize = bfd_section_size (abfd, strsec);
+ strings = (bfd_byte *) xmalloc (strsize);
+ if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize))
+ {
+ fprintf (stderr, "%s: %s: %s\n",
+ bfd_get_filename (abfd), names[i].strsecname,
+ bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+
+ if (shandle == NULL)
+ {
+ shandle = start_stab (dhandle, abfd, true, syms, symcount);
+ if (shandle == NULL)
+ return false;
+ }
+
+ *pfound = true;
+
+ stroff = 0;
+ next_stroff = 0;
+ for (stab = stabs; stab < stabs + stabsize; stab += 12)
+ {
+ bfd_size_type strx;
+ int type;
+ int other;
+ int desc;
+ bfd_vma value;
+
+ /* This code presumes 32 bit values. */
+
+ strx = bfd_get_32 (abfd, stab);
+ type = bfd_get_8 (abfd, stab + 4);
+ other = bfd_get_8 (abfd, stab + 5);
+ desc = bfd_get_16 (abfd, stab + 6);
+ value = bfd_get_32 (abfd, stab + 8);
+
+ if (type == 0)
+ {
+ /* Special type 0 stabs indicate the offset to the
+ next string table. */
+ stroff = next_stroff;
+ next_stroff += value;
+ }
+ else
+ {
+ char *f, *s;
+
+ f = NULL;
+ s = (char *) strings + stroff + strx;
+ while (s[strlen (s) - 1] == '\\'
+ && stab + 12 < stabs + stabsize)
+ {
+ stab += 12;
+ s[strlen (s) - 1] = '\0';
+ s = concat (s,
+ ((char *) strings
+ + stroff
+ + bfd_get_32 (abfd, stab)),
+ (const char *) NULL);
+ if (f != NULL)
+ free (f);
+ f = s;
+ }
+
+ save_stab (type, desc, value, s);
+
+ if (! parse_stab (dhandle, shandle, type, desc, value, s))
+ {
+ stab_context ();
+ free_saved_stabs ();
+ return false;
+ }
+
+ /* Don't free f, since I think the stabs code
+ expects strings to hang around. This should be
+ straightened out. FIXME. */
+ }
+ }
+
+ free_saved_stabs ();
+ free (stabs);
+
+ /* Don't free strings, since I think the stabs code expects
+ the strings to hang around. This should be straightened
+ out. FIXME. */
+ }
+ }
+
+ if (shandle != NULL)
+ {
+ if (! finish_stab (dhandle, shandle))
+ return false;
+ }
+
+ return true;
+}
+
+/* Read stabs in the symbol table. */
+
+static boolean
+read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle, pfound)
+ bfd *abfd;
+ asymbol **syms;
+ long symcount;
+ PTR dhandle;
+ boolean *pfound;
+{
+ PTR shandle;
+ asymbol **ps, **symend;
+
+ shandle = NULL;
+ symend = syms + symcount;
+ for (ps = syms; ps < symend; ps++)
+ {
+ symbol_info i;
+
+ bfd_get_symbol_info (abfd, *ps, &i);
+
+ if (i.type == '-')
+ {
+ const char *s;
+ char *f;
+
+ if (shandle == NULL)
+ {
+ shandle = start_stab (dhandle, abfd, false, syms, symcount);
+ if (shandle == NULL)
+ return false;
+ }
+
+ *pfound = true;
+
+ s = i.name;
+ while (s[strlen (s) - 1] == '\\'
+ && ps + 1 < symend)
+ {
+ char *sc, *n;
+
+ ++ps;
+ sc = xstrdup (s);
+ sc[strlen (sc) - 1] = '\0';
+ n = concat (sc, bfd_asymbol_name (*ps), (const char *) NULL);
+ free (sc);
+ if (f != NULL)
+ free (f);
+ f = n;
+ s = n;
+ }
+
+ save_stab (i.stab_type, i.stab_desc, i.value, s);
+
+ if (! parse_stab (dhandle, shandle, i.stab_type, i.stab_desc,
+ i.value, s))
+ {
+ stab_context ();
+ free_saved_stabs ();
+ return false;
+ }
+
+ /* Don't free f, since I think the stabs code expects
+ strings to hang around. This should be straightened out.
+ FIXME. */
+ }
+ }
+
+ free_saved_stabs ();
+
+ if (shandle != NULL)
+ {
+ if (! finish_stab (dhandle, shandle))
+ return false;
+ }
+
+ return true;
+}
+
+/* Read IEEE debugging information. */
+
+static boolean
+read_ieee_debugging_info (abfd, dhandle, pfound)
+ bfd *abfd;
+ PTR dhandle;
+ boolean *pfound;
+{
+ asection *dsec;
+ bfd_size_type size;
+ bfd_byte *contents;
+
+ /* The BFD backend puts the debugging information into a section
+ named .debug. */
+
+ dsec = bfd_get_section_by_name (abfd, ".debug");
+ if (dsec == NULL)
+ return true;
+
+ size = bfd_section_size (abfd, dsec);
+ contents = (bfd_byte *) xmalloc (size);
+ if (! bfd_get_section_contents (abfd, dsec, contents, 0, size))
+ return false;
+
+ if (! parse_ieee (dhandle, abfd, contents, size))
+ return false;
+
+ free (contents);
+
+ *pfound = true;
+
+ return true;
+}
+
+/* Record stabs strings, so that we can give some context for errors. */
+
+#define SAVE_STABS_COUNT (16)
+
+struct saved_stab
+{
+ int type;
+ int desc;
+ bfd_vma value;
+ char *string;
+};
+
+static struct saved_stab saved_stabs[SAVE_STABS_COUNT];
+static int saved_stabs_index;
+
+/* Save a stabs string. */
+
+static void
+save_stab (type, desc, value, string)
+ int type;
+ int desc;
+ bfd_vma value;
+ const char *string;
+{
+ if (saved_stabs[saved_stabs_index].string != NULL)
+ free (saved_stabs[saved_stabs_index].string);
+ saved_stabs[saved_stabs_index].type = type;
+ saved_stabs[saved_stabs_index].desc = desc;
+ saved_stabs[saved_stabs_index].value = value;
+ saved_stabs[saved_stabs_index].string = xstrdup (string);
+ saved_stabs_index = (saved_stabs_index + 1) % SAVE_STABS_COUNT;
+}
+
+/* Provide context for an error. */
+
+static void
+stab_context ()
+{
+ int i;
+
+ fprintf (stderr, "Last stabs entries before error:\n");
+ fprintf (stderr, "n_type n_desc n_value string\n");
+
+ i = saved_stabs_index;
+ do
+ {
+ struct saved_stab *stabp;
+
+ stabp = saved_stabs + i;
+ if (stabp->string != NULL)
+ {
+ const char *s;
+
+ s = bfd_get_stab_name (stabp->type);
+ if (s != NULL)
+ fprintf (stderr, "%-6s", s);
+ else if (stabp->type == 0)
+ fprintf (stderr, "HdrSym");
+ else
+ fprintf (stderr, "%-6d", stabp->type);
+ fprintf (stderr, " %-6d ", stabp->desc);
+ fprintf_vma (stderr, stabp->value);
+ if (stabp->type != 0)
+ fprintf (stderr, " %s", stabp->string);
+ fprintf (stderr, "\n");
+ }
+ i = (i + 1) % SAVE_STABS_COUNT;
+ }
+ while (i != saved_stabs_index);
+}
+
+/* Free the saved stab strings. */
+
+static void
+free_saved_stabs ()
+{
+ int i;
+
+ for (i = 0; i < SAVE_STABS_COUNT; i++)
+ if (saved_stabs[i].string != NULL)
+ free (saved_stabs[i].string);
+ saved_stabs_index = 0;
+}
diff --git a/gnu/usr.bin/binutils/binutils/stabs.c b/gnu/usr.bin/binutils/binutils/stabs.c
new file mode 100644
index 00000000000..af43fea303d
--- /dev/null
+++ b/gnu/usr.bin/binutils/binutils/stabs.c
@@ -0,0 +1,4967 @@
+/* stabs.c -- Parse stabs debugging information
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ 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. */
+
+/* This file contains code which parses stabs debugging information.
+ The organization of this code is based on the gdb stabs reading
+ code. The job it does is somewhat different, because it is not
+ trying to identify the correct address for anything. */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "demangle.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* Meaningless definition needs by aout64.h. FIXME. */
+#define BYTES_IN_WORD 4
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+
+/* The number of predefined XCOFF types. */
+
+#define XCOFF_TYPE_COUNT 34
+
+/* This structure is used as a handle so that the stab parsing doesn't
+ need to use any static variables. */
+
+struct stab_handle
+{
+ /* The BFD. */
+ bfd *abfd;
+ /* True if this is stabs in sections. */
+ boolean sections;
+ /* The symbol table. */
+ asymbol **syms;
+ /* The number of symbols. */
+ long symcount;
+ /* The accumulated file name string. */
+ char *so_string;
+ /* The value of the last N_SO symbol. */
+ bfd_vma so_value;
+ /* The value of the start of the file, so that we can handle file
+ relative N_LBRAC and N_RBRAC symbols. */
+ bfd_vma file_start_offset;
+ /* The offset of the start of the function, so that we can handle
+ function relative N_LBRAC and N_RBRAC symbols. */
+ bfd_vma function_start_offset;
+ /* The version number of gcc which compiled the current compilation
+ unit, 0 if not compiled by gcc. */
+ int gcc_compiled;
+ /* Whether an N_OPT symbol was seen that was not generated by gcc,
+ so that we can detect the SunPRO compiler. */
+ boolean n_opt_found;
+ /* The main file name. */
+ char *main_filename;
+ /* A stack of N_BINCL files. */
+ struct bincl_file *bincl_stack;
+ /* Whether we are inside a function or not. */
+ boolean within_function;
+ /* The depth of block nesting. */
+ int block_depth;
+ /* List of pending variable definitions. */
+ struct stab_pending_var *pending;
+ /* Number of files for which we have types. */
+ unsigned int files;
+ /* Lists of types per file. */
+ struct stab_types **file_types;
+ /* Predefined XCOFF types. */
+ debug_type xcoff_types[XCOFF_TYPE_COUNT];
+ /* Undefined tags. */
+ struct stab_tag *tags;
+};
+
+/* A list of these structures is used to hold pending variable
+ definitions seen before the N_LBRAC of a block. */
+
+struct stab_pending_var
+{
+ /* Next pending variable definition. */
+ struct stab_pending_var *next;
+ /* Name. */
+ const char *name;
+ /* Type. */
+ debug_type type;
+ /* Kind. */
+ enum debug_var_kind kind;
+ /* Value. */
+ bfd_vma val;
+};
+
+/* A list of these structures is used to hold the types for a single
+ file. */
+
+struct stab_types
+{
+ /* Next set of slots for this file. */
+ struct stab_types *next;
+ /* Types indexed by type number. */
+#define STAB_TYPES_SLOTS (16)
+ debug_type types[STAB_TYPES_SLOTS];
+};
+
+/* We keep a list of undefined tags that we encounter, so that we can
+ fill them in if the tag is later defined. */
+
+struct stab_tag
+{
+ /* Next undefined tag. */
+ struct stab_tag *next;
+ /* Tag name. */
+ const char *name;
+ /* Type kind. */
+ enum debug_type_kind kind;
+ /* Slot to hold real type when we discover it. If we don't, we fill
+ in an undefined tag type. */
+ debug_type slot;
+ /* Indirect type we have created to point at slot. */
+ debug_type type;
+};
+
+static char *savestring PARAMS ((const char *, int));
+static bfd_vma parse_number PARAMS ((const char **, boolean *));
+static void bad_stab PARAMS ((const char *));
+static void warn_stab PARAMS ((const char *, const char *));
+static boolean parse_stab_string
+ PARAMS ((PTR, struct stab_handle *, int, int, bfd_vma, const char *));
+static debug_type parse_stab_type
+ PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+ debug_type **));
+static boolean parse_stab_type_number
+ PARAMS ((const char **, int *));
+static debug_type parse_stab_range_type
+ PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+ const int *));
+static debug_type parse_stab_sun_builtin_type PARAMS ((PTR, const char **));
+static debug_type parse_stab_sun_floating_type
+ PARAMS ((PTR, const char **));
+static debug_type parse_stab_enum_type PARAMS ((PTR, const char **));
+static debug_type parse_stab_struct_type
+ PARAMS ((PTR, struct stab_handle *, const char *, const char **, boolean,
+ const int *));
+static boolean parse_stab_baseclasses
+ PARAMS ((PTR, struct stab_handle *, const char **, debug_baseclass **));
+static boolean parse_stab_struct_fields
+ PARAMS ((PTR, struct stab_handle *, const char **, debug_field **,
+ boolean *));
+static boolean parse_stab_cpp_abbrev
+ PARAMS ((PTR, struct stab_handle *, const char **, debug_field *));
+static boolean parse_stab_one_struct_field
+ PARAMS ((PTR, struct stab_handle *, const char **, const char *,
+ debug_field *, boolean *));
+static boolean parse_stab_members
+ PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+ const int *, debug_method **));
+static debug_type parse_stab_argtypes
+ PARAMS ((PTR, struct stab_handle *, debug_type, const char *, const char *,
+ debug_type, const char *, boolean, boolean, const char **));
+static boolean parse_stab_tilde_field
+ PARAMS ((PTR, struct stab_handle *, const char **, const int *,
+ debug_type *, boolean *));
+static debug_type parse_stab_array_type
+ PARAMS ((PTR, struct stab_handle *, const char **, boolean));
+static void push_bincl PARAMS ((struct stab_handle *, const char *));
+static const char *pop_bincl PARAMS ((struct stab_handle *));
+static boolean stab_record_variable
+ PARAMS ((PTR, struct stab_handle *, const char *, debug_type,
+ enum debug_var_kind, bfd_vma));
+static boolean stab_emit_pending_vars PARAMS ((PTR, struct stab_handle *));
+static debug_type *stab_find_slot
+ PARAMS ((struct stab_handle *, const int *));
+static debug_type stab_find_type
+ PARAMS ((PTR, struct stab_handle *, const int *));
+static boolean stab_record_type
+ PARAMS ((PTR, struct stab_handle *, const int *, debug_type));
+static debug_type stab_xcoff_builtin_type
+ PARAMS ((PTR, struct stab_handle *, int));
+static debug_type stab_find_tagged_type
+ PARAMS ((PTR, struct stab_handle *, const char *, int,
+ enum debug_type_kind));
+static debug_type *stab_demangle_argtypes
+ PARAMS ((PTR, struct stab_handle *, const char *, boolean *));
+
+/* Save a string in memory. */
+
+static char *
+savestring (start, len)
+ const char *start;
+ int len;
+{
+ char *ret;
+
+ ret = (char *) xmalloc (len + 1);
+ memcpy (ret, start, len);
+ ret[len] = '\0';
+ return ret;
+}
+
+/* Read a number from a string. */
+
+static bfd_vma
+parse_number (pp, poverflow)
+ const char **pp;
+ boolean *poverflow;
+{
+ unsigned long ul;
+ const char *orig;
+
+ if (poverflow != NULL)
+ *poverflow = false;
+
+ orig = *pp;
+
+ errno = 0;
+ ul = strtoul (*pp, (char **) pp, 0);
+ if (ul + 1 != 0 || errno == 0)
+ return (bfd_vma) ul;
+
+ /* Note that even though strtoul overflowed, it should have set *pp
+ to the end of the number, which is where we want it. */
+
+ if (sizeof (bfd_vma) > sizeof (unsigned long))
+ {
+ const char *p;
+ boolean neg;
+ int base;
+ bfd_vma over, lastdig;
+ boolean overflow;
+ bfd_vma v;
+
+ /* Our own version of strtoul, for a bfd_vma. */
+
+ p = orig;
+
+ neg = false;
+ if (*p == '+')
+ ++p;
+ else if (*p == '-')
+ {
+ neg = true;
+ ++p;
+ }
+
+ base = 10;
+ if (*p == '0')
+ {
+ if (p[1] == 'x' || p[1] == 'X')
+ {
+ base = 16;
+ p += 2;
+ }
+ else
+ {
+ base = 8;
+ ++p;
+ }
+ }
+
+ over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base;
+ lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base;
+
+ overflow = false;
+ v = 0;
+ while (1)
+ {
+ int d;
+
+ d = *p++;
+ if (isdigit ((unsigned char) d))
+ d -= '0';
+ else if (isupper ((unsigned char) d))
+ d -= 'A';
+ else if (islower ((unsigned char) d))
+ d -= 'a';
+ else
+ break;
+
+ if (d >= base)
+ break;
+
+ if (v > over || (v == over && (bfd_vma) d > lastdig))
+ {
+ overflow = true;
+ break;
+ }
+ }
+
+ if (! overflow)
+ {
+ if (neg)
+ v = - v;
+ return v;
+ }
+ }
+
+ /* If we get here, the number is too large to represent in a
+ bfd_vma. */
+
+ if (poverflow != NULL)
+ *poverflow = true;
+ else
+ warn_stab (orig, "numeric overflow");
+
+ return 0;
+}
+
+/* Give an error for a bad stab string. */
+
+static void
+bad_stab (p)
+ const char *p;
+{
+ fprintf (stderr, "Bad stab: %s\n", p);
+}
+
+/* Warn about something in a stab string. */
+
+static void
+warn_stab (p, err)
+ const char *p;
+ const char *err;
+{
+ fprintf (stderr, "Warning: %s: %s\n", err, p);
+}
+
+/* Create a handle to parse stabs symbols with. */
+
+/*ARGSUSED*/
+PTR
+start_stab (dhandle, abfd, sections, syms, symcount)
+ PTR dhandle;
+ bfd *abfd;
+ boolean sections;
+ asymbol **syms;
+ long symcount;
+{
+ struct stab_handle *ret;
+
+ ret = (struct stab_handle *) xmalloc (sizeof *ret);
+ memset (ret, 0, sizeof *ret);
+ ret->abfd = abfd;
+ ret->sections = sections;
+ ret->syms = syms;
+ ret->symcount = symcount;
+ ret->files = 1;
+ ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types);
+ ret->file_types[0] = NULL;
+ return (PTR) ret;
+}
+
+/* When we have processed all the stabs information, we need to go
+ through and fill in all the undefined tags. */
+
+boolean
+finish_stab (dhandle, handle)
+ PTR dhandle;
+ PTR handle;
+{
+ struct stab_handle *info = (struct stab_handle *) handle;
+ struct stab_tag *st;
+
+ if (info->within_function)
+ {
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, (bfd_vma) -1))
+ return false;
+ info->within_function = false;
+ }
+
+ for (st = info->tags; st != NULL; st = st->next)
+ {
+ enum debug_type_kind kind;
+
+ kind = st->kind;
+ if (kind == DEBUG_KIND_ILLEGAL)
+ kind = DEBUG_KIND_STRUCT;
+ st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind);
+ if (st->slot == DEBUG_TYPE_NULL)
+ return false;
+ }
+
+ return true;
+}
+
+/* Handle a single stabs symbol. */
+
+boolean
+parse_stab (dhandle, handle, type, desc, value, string)
+ PTR dhandle;
+ PTR handle;
+ int type;
+ int desc;
+ bfd_vma value;
+ const char *string;
+{
+ struct stab_handle *info = (struct stab_handle *) handle;
+
+ /* gcc will emit two N_SO strings per compilation unit, one for the
+ directory name and one for the file name. We just collect N_SO
+ strings as we see them, and start the new compilation unit when
+ we see a non N_SO symbol. */
+ if (info->so_string != NULL
+ && (type != N_SO || *string == '\0' || value != info->so_value))
+ {
+ if (! debug_set_filename (dhandle, info->so_string))
+ return false;
+ info->main_filename = info->so_string;
+
+ info->gcc_compiled = 0;
+ info->n_opt_found = false;
+
+ /* Generally, for stabs in the symbol table, the N_LBRAC and
+ N_RBRAC symbols are relative to the N_SO symbol value. */
+ if (! info->sections)
+ info->file_start_offset = info->so_value;
+
+ /* We need to reset the mapping from type numbers to types. We
+ can't free the old mapping, because of the use of
+ debug_make_indirect_type. */
+ info->files = 1;
+ info->file_types = ((struct stab_types **)
+ xmalloc (sizeof *info->file_types));
+ info->file_types[0] = NULL;
+
+ info->so_string = NULL;
+
+ /* Now process whatever type we just got. */
+ }
+
+ switch (type)
+ {
+ case N_FN:
+ case N_FN_SEQ:
+ break;
+
+ case N_LBRAC:
+ /* Ignore extra outermost context from SunPRO cc and acc. */
+ if (info->n_opt_found && desc == 1)
+ break;
+
+ if (! info->within_function)
+ {
+ fprintf (stderr, "N_LBRAC not within function\n");
+ return false;
+ }
+
+ /* Start an inner lexical block. */
+ if (! debug_start_block (dhandle,
+ (value
+ + info->file_start_offset
+ + info->function_start_offset)))
+ return false;
+
+ /* Emit any pending variable definitions. */
+ if (! stab_emit_pending_vars (dhandle, info))
+ return false;
+
+ ++info->block_depth;
+ break;
+
+ case N_RBRAC:
+ /* Ignore extra outermost context from SunPRO cc and acc. */
+ if (info->n_opt_found && desc == 1)
+ break;
+
+ /* We shouldn't have any pending variable definitions here, but,
+ if we do, we probably need to emit them before closing the
+ block. */
+ if (! stab_emit_pending_vars (dhandle, info))
+ return false;
+
+ /* End an inner lexical block. */
+ if (! debug_end_block (dhandle,
+ (value
+ + info->file_start_offset
+ + info->function_start_offset)))
+ return false;
+
+ --info->block_depth;
+ if (info->block_depth < 0)
+ {
+ fprintf (stderr, "Too many N_RBRACs\n");
+ return false;
+ }
+ break;
+
+ case N_SO:
+ /* This always ends a function. */
+ if (info->within_function)
+ {
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, value))
+ return false;
+ info->within_function = false;
+ }
+
+ /* An empty string is emitted by gcc at the end of a compilation
+ unit. */
+ if (*string == '\0')
+ return true;
+
+ /* Just accumulate strings until we see a non N_SO symbol. If
+ the string starts with '/', we discard the previously
+ accumulated strings. */
+ if (info->so_string == NULL)
+ info->so_string = xstrdup (string);
+ else
+ {
+ char *f;
+
+ f = info->so_string;
+ if (*string == '/')
+ info->so_string = xstrdup (string);
+ else
+ info->so_string = concat (info->so_string, string,
+ (const char *) NULL);
+ free (f);
+ }
+
+ info->so_value = value;
+
+ break;
+
+ case N_SOL:
+ /* Start an include file. */
+ if (! debug_start_source (dhandle, string))
+ return false;
+ break;
+
+ case N_BINCL:
+ /* Start an include file which may be replaced. */
+ push_bincl (info, string);
+ if (! debug_start_source (dhandle, string))
+ return false;
+ break;
+
+ case N_EINCL:
+ /* End an N_BINCL include. */
+ if (! debug_start_source (dhandle, pop_bincl (info)))
+ return false;
+ break;
+
+ case N_EXCL:
+ /* This is a duplicate of a header file named by N_BINCL which
+ was eliminated by the linker. */
+ ++info->files;
+ info->file_types = ((struct stab_types **)
+ xrealloc ((PTR) info->file_types,
+ (info->files
+ * sizeof *info->file_types)));
+ info->file_types[info->files - 1] = NULL;
+ break;
+
+ case N_SLINE:
+ if (! debug_record_line (dhandle, desc,
+ value + info->function_start_offset))
+ return false;
+ break;
+
+ case N_BCOMM:
+ if (! debug_start_common_block (dhandle, string))
+ return false;
+ break;
+
+ case N_ECOMM:
+ if (! debug_end_common_block (dhandle, string))
+ return false;
+ break;
+
+ /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
+ symbols, and if it does not start with :S, gdb relocates the
+ value to the start of the section. gcc always seems to use
+ :S, so we don't worry about this. */
+ default:
+ {
+ const char *colon;
+
+ colon = strchr (string, ':');
+ if (colon != NULL
+ && (colon[1] == 'f' || colon[1] == 'F'))
+ {
+ if (info->within_function)
+ {
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, value))
+ return false;
+ }
+ /* For stabs in sections, line numbers and block addresses
+ are offsets from the start of the function. */
+ if (info->sections)
+ info->function_start_offset = value;
+ info->within_function = true;
+ }
+
+ if (! parse_stab_string (dhandle, info, type, desc, value, string))
+ return false;
+ }
+ break;
+
+ case N_OPT:
+ if (string != NULL && strcmp (string, "gcc2_compiled.") == 0)
+ info->gcc_compiled = 2;
+ else if (string != NULL && strcmp (string, "gcc_compiled.") == 0)
+ info->gcc_compiled = 1;
+ else
+ info->n_opt_found = true;
+ break;
+
+ case N_OBJ:
+ case N_ENDM:
+ case N_MAIN:
+ break;
+ }
+
+ return true;
+}
+
+/* Parse the stabs string. */
+
+static boolean
+parse_stab_string (dhandle, info, stabtype, desc, value, string)
+ PTR dhandle;
+ struct stab_handle *info;
+ int stabtype;
+ int desc;
+ bfd_vma value;
+ const char *string;
+{
+ const char *p;
+ char *name;
+ int type;
+ debug_type dtype;
+ boolean synonym;
+ unsigned int lineno;
+ debug_type *slot;
+
+ p = strchr (string, ':');
+ if (p == NULL)
+ return true;
+
+ while (p[1] == ':')
+ {
+ p += 2;
+ p = strchr (p, ':');
+ if (p == NULL)
+ {
+ bad_stab (string);
+ return false;
+ }
+ }
+
+ /* GCC 2.x puts the line number in desc. SunOS apparently puts in
+ the number of bytes occupied by a type or object, which we
+ ignore. */
+ if (info->gcc_compiled >= 2)
+ lineno = desc;
+ else
+ lineno = 0;
+
+ /* FIXME: Sometimes the special C++ names start with '.'. */
+ name = NULL;
+ if (string[0] == '$')
+ {
+ switch (string[1])
+ {
+ case 't':
+ name = "this";
+ break;
+ case 'v':
+ /* Was: name = "vptr"; */
+ break;
+ case 'e':
+ name = "eh_throw";
+ break;
+ case '_':
+ /* This was an anonymous type that was never fixed up. */
+ break;
+ case 'X':
+ /* SunPRO (3.0 at least) static variable encoding. */
+ break;
+ default:
+ warn_stab (string, "unknown C++ encoded name");
+ break;
+ }
+ }
+
+ if (name == NULL)
+ {
+ if (p == string || (string[0] == ' ' && p == string + 1))
+ name = NULL;
+ else
+ name = savestring (string, p - string);
+ }
+
+ ++p;
+ if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+ type = 'l';
+ else
+ type = *p++;
+
+ switch (type)
+ {
+ case 'c':
+ /* c is a special case, not followed by a type-number.
+ SYMBOL:c=iVALUE for an integer constant symbol.
+ SYMBOL:c=rVALUE for a floating constant symbol.
+ SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
+ e.g. "b:c=e6,0" for "const b = blob1"
+ (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
+ if (*p != '=')
+ {
+ bad_stab (string);
+ return false;
+ }
+ ++p;
+ switch (*p++)
+ {
+ case 'r':
+ /* Floating point constant. */
+ if (! debug_record_float_const (dhandle, name, atof (p)))
+ return false;
+ break;
+ case 'i':
+ /* Integer constant. */
+ /* Defining integer constants this way is kind of silly,
+ since 'e' constants allows the compiler to give not only
+ the value, but the type as well. C has at least int,
+ long, unsigned int, and long long as constant types;
+ other languages probably should have at least unsigned as
+ well as signed constants. */
+ if (! debug_record_int_const (dhandle, name, atoi (p)))
+ return false;
+ break;
+ case 'e':
+ /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value
+ can be represented as integral.
+ e.g. "b:c=e6,0" for "const b = blob1"
+ (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+ &p, (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (*p != ',')
+ {
+ bad_stab (string);
+ return false;
+ }
+ if (! debug_record_typed_const (dhandle, name, dtype, atoi (p)))
+ return false;
+ break;
+ default:
+ bad_stab (string);
+ return false;
+ }
+
+ break;
+
+ case 'C':
+ /* The name of a caught exception. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+ &p, (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_label (dhandle, name, dtype, value))
+ return false;
+ break;
+
+ case 'f':
+ case 'F':
+ /* A function definition. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
+ return false;
+
+ /* Sun acc puts declared types of arguments here. We don't care
+ about their actual types (FIXME -- we should remember the whole
+ function prototype), but the list may define some new types
+ that we have to remember, so we must scan it now. */
+ while (*p == ';')
+ {
+ ++p;
+ if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL)
+ == DEBUG_TYPE_NULL)
+ return false;
+ }
+
+ break;
+
+ case 'G':
+ {
+ char leading;
+ long c;
+ asymbol **ps;
+
+ /* A global symbol. The value must be extracted from the
+ symbol table. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ leading = bfd_get_symbol_leading_char (info->abfd);
+ for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
+ {
+ const char *n;
+
+ n = bfd_asymbol_name (*ps);
+ if (leading != '\0' && *n == leading)
+ ++n;
+ if (*n == *name && strcmp (n, name) == 0)
+ break;
+ }
+ if (c > 0)
+ value = bfd_asymbol_value (*ps);
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
+ value))
+ return false;
+ }
+ break;
+
+ /* This case is faked by a conditional above, when there is no
+ code letter in the dbx data. Dbx data never actually
+ contains 'l'. */
+ case 'l':
+ case 's':
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
+ value))
+ return false;
+ break;
+
+ case 'p':
+ /* A function parameter. */
+ if (*p != 'F')
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ else
+ {
+ /* pF is a two-letter code that means a function parameter in
+ Fortran. The type-number specifies the type of the return
+ value. Translate it into a pointer-to-function type. */
+ ++p;
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype != DEBUG_TYPE_NULL)
+ {
+ debug_type ftype;
+
+ ftype = debug_make_function_type (dhandle, dtype,
+ (debug_type *) NULL, false);
+ dtype = debug_make_pointer_type (dhandle, ftype);
+ }
+ }
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK,
+ value))
+ return false;
+
+ /* FIXME: At this point gdb considers rearranging the parameter
+ address on a big endian machine if it is smaller than an int.
+ We have no way to do that, since we don't really know much
+ about the target. */
+
+ break;
+
+ case 'P':
+ if (stabtype == N_FUN)
+ {
+ /* Prototype of a function referenced by this file. */
+ while (*p == ';')
+ {
+ ++p;
+ if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL)
+ == DEBUG_TYPE_NULL)
+ return false;
+ }
+ break;
+ }
+ /* Fall through. */
+ case 'R':
+ /* Parameter which is in a register. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
+ value))
+ return false;
+ break;
+
+ case 'r':
+ /* Register variable (either global or local). */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER,
+ value))
+ return false;
+
+ /* FIXME: At this point gdb checks to combine pairs of 'p' and
+ 'r' stabs into a single 'P' stab. */
+
+ break;
+
+ case 'S':
+ /* Static symbol at top level of file */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC,
+ value))
+ return false;
+ break;
+
+ case 't':
+ /* A typedef. */
+ dtype = parse_stab_type (dhandle, info, name, &p, &slot);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (name == NULL)
+ {
+ /* A nameless type. Nothing to do. */
+ return true;
+ }
+
+ dtype = debug_name_type (dhandle, name, dtype);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+
+ if (slot != NULL)
+ *slot = dtype;
+
+ break;
+
+ case 'T':
+ /* Struct, union, or enum tag. For GNU C++, this can be be followed
+ by 't' which means we are typedef'ing it as well. */
+ if (*p != 't')
+ {
+ synonym = false;
+ /* FIXME: gdb sets synonym to true if the current language
+ is C++. */
+ }
+ else
+ {
+ synonym = true;
+ ++p;
+ }
+
+ dtype = parse_stab_type (dhandle, info, name, &p, &slot);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (name == NULL)
+ return true;
+
+ dtype = debug_tag_type (dhandle, name, dtype);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (slot != NULL)
+ *slot = dtype;
+
+ /* See if we have a cross reference to this tag which we can now
+ fill in. */
+ {
+ register struct stab_tag **pst;
+
+ for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next)
+ {
+ if ((*pst)->name[0] == name[0]
+ && strcmp ((*pst)->name, name) == 0)
+ {
+ (*pst)->slot = dtype;
+ *pst = (*pst)->next;
+ break;
+ }
+ }
+ }
+
+ if (synonym)
+ {
+ dtype = debug_name_type (dhandle, name, dtype);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+
+ if (slot != NULL)
+ *slot = dtype;
+ }
+
+ break;
+
+ case 'V':
+ /* Static symbol of local scope */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ /* FIXME: gdb checks os9k_stabs here. */
+ if (! stab_record_variable (dhandle, info, name, dtype,
+ DEBUG_LOCAL_STATIC, value))
+ return false;
+ break;
+
+ case 'v':
+ /* Reference parameter. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
+ value))
+ return false;
+ break;
+
+ case 'a':
+ /* Reference parameter which is in a register. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
+ value))
+ return false;
+ break;
+
+ case 'X':
+ /* This is used by Sun FORTRAN for "function result value".
+ Sun claims ("dbx and dbxtool interfaces", 2nd ed)
+ that Pascal uses it too, but when I tried it Pascal used
+ "x:3" (local symbol) instead. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
+ value))
+ return false;
+ break;
+
+ default:
+ bad_stab (string);
+ return false;
+ }
+
+ /* FIXME: gdb converts structure values to structure pointers in a
+ couple of cases, depending upon the target. */
+
+ return true;
+}
+
+/* Parse a stabs type. The typename argument is non-NULL if this is a
+ typedef or a tag definition. The pp argument points to the stab
+ string, and is updated. The slotp argument points to a place to
+ store the slot used if the type is being defined. */
+
+static debug_type
+parse_stab_type (dhandle, info, typename, pp, slotp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *typename;
+ const char **pp;
+ debug_type **slotp;
+{
+ const char *orig;
+ int typenums[2];
+ int size;
+ boolean stringp;
+ int descriptor;
+ debug_type dtype;
+
+ if (slotp != NULL)
+ *slotp = NULL;
+
+ orig = *pp;
+
+ size = -1;
+ stringp = false;
+
+ /* Read type number if present. The type number may be omitted.
+ for instance in a two-dimensional array declared with type
+ "ar1;1;10;ar1;1;10;4". */
+ if (! isdigit ((unsigned char) **pp) && **pp != '(' && **pp != '-')
+ {
+ /* 'typenums=' not present, type is anonymous. Read and return
+ the definition, but don't put it in the type vector. */
+ typenums[0] = typenums[1] = -1;
+ }
+ else
+ {
+ if (! parse_stab_type_number (pp, typenums))
+ return DEBUG_TYPE_NULL;
+
+ if (**pp != '=')
+ {
+ /* Type is not being defined here. Either it already
+ exists, or this is a forward reference to it. */
+ return stab_find_type (dhandle, info, typenums);
+ }
+
+ /* Only set the slot if the type is being defined. This means
+ that the mapping from type numbers to types will only record
+ the name of the typedef which defines a type. If we don't do
+ this, then something like
+ typedef int foo;
+ int i;
+ will record that i is of type foo. Unfortunately, stabs
+ information is ambiguous about variable types. For this code,
+ typedef int foo;
+ int i;
+ foo j;
+ the stabs information records both i and j as having the same
+ type. This could be fixed by patching the compiler. */
+ if (slotp != NULL && typenums[0] >= 0 && typenums[1] >= 0)
+ *slotp = stab_find_slot (info, typenums);
+
+ /* Type is being defined here. */
+ /* Skip the '='. */
+ ++*pp;
+
+ while (**pp == '@')
+ {
+ const char *p = *pp + 1;
+ const char *attr;
+
+ if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+ {
+ /* Member type. */
+ break;
+ }
+
+ /* Type attributes. */
+ attr = p;
+
+ for (; *p != ';'; ++p)
+ {
+ if (*p == '\0')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ }
+ *pp = p + 1;
+
+ switch (*attr)
+ {
+ case 's':
+ size = atoi (attr + 1);
+ if (size <= 0)
+ size = -1;
+ break;
+
+ case 'S':
+ stringp = true;
+ break;
+
+ default:
+ /* Ignore unrecognized type attributes, so future
+ compilers can invent new ones. */
+ break;
+ }
+ }
+ }
+
+ descriptor = **pp;
+ ++*pp;
+
+ switch (descriptor)
+ {
+ case 'x':
+ {
+ enum debug_type_kind code;
+ const char *q1, *q2, *p;
+
+ /* A cross reference to another type. */
+
+ switch (**pp)
+ {
+ case 's':
+ code = DEBUG_KIND_STRUCT;
+ break;
+ case 'u':
+ code = DEBUG_KIND_UNION;
+ break;
+ case 'e':
+ code = DEBUG_KIND_ENUM;
+ break;
+ default:
+ /* Complain and keep going, so compilers can invent new
+ cross-reference types. */
+ warn_stab (orig, "unrecognized cross reference type");
+ code = DEBUG_KIND_STRUCT;
+ break;
+ }
+ ++*pp;
+
+ q1 = strchr (*pp, '<');
+ p = strchr (*pp, ':');
+ if (p == NULL)
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ while (q1 != NULL && p > q1 && p[1] == ':')
+ {
+ q2 = strchr (q1, '>');
+ if (q2 == NULL || q2 < p)
+ break;
+ p += 2;
+ p = strchr (p, ':');
+ if (p == NULL)
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ }
+
+ dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);
+
+ *pp = p + 1;
+ }
+ break;
+
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '(':
+ {
+ const char *hold;
+ int xtypenums[2];
+
+ /* This type is defined as another type. */
+
+ (*pp)--;
+ hold = *pp;
+
+ /* Peek ahead at the number to detect void. */
+ if (! parse_stab_type_number (pp, xtypenums))
+ return DEBUG_TYPE_NULL;
+
+ if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1])
+ {
+ /* This type is being defined as itself, which means that
+ it is void. */
+ dtype = debug_make_void_type (dhandle);
+ }
+ else
+ {
+ *pp = hold;
+
+ /* Go back to the number and have parse_stab_type get it.
+ This means that we can deal with something like
+ t(1,2)=(3,4)=... which the Lucid compiler uses. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (typenums[0] != -1)
+ {
+ if (! stab_record_type (dhandle, info, typenums, dtype))
+ return DEBUG_TYPE_NULL;
+ }
+
+ break;
+ }
+
+ case '*':
+ dtype = debug_make_pointer_type (dhandle,
+ parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
+ (debug_type **) NULL));
+ break;
+
+ case '&':
+ /* Reference to another type. */
+ dtype = (debug_make_reference_type
+ (dhandle,
+ parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL)));
+ break;
+
+ case 'f':
+ /* Function returning another type. */
+ /* FIXME: gdb checks os9k_stabs here. */
+ dtype = (debug_make_function_type
+ (dhandle,
+ parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL),
+ (debug_type *) NULL, false));
+ break;
+
+ case 'k':
+ /* Const qualifier on some type (Sun). */
+ /* FIXME: gdb accepts 'c' here if os9k_stabs. */
+ dtype = debug_make_const_type (dhandle,
+ parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
+ (debug_type **) NULL));
+ break;
+
+ case 'B':
+ /* Volatile qual on some type (Sun). */
+ /* FIXME: gdb accepts 'i' here if os9k_stabs. */
+ dtype = (debug_make_volatile_type
+ (dhandle,
+ parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL)));
+ break;
+
+ case '@':
+ /* Offset (class & variable) type. This is used for a pointer
+ relative to an object. */
+ {
+ debug_type domain;
+ debug_type memtype;
+
+ /* Member type. */
+
+ domain = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (domain == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (memtype == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ dtype = debug_make_offset_type (dhandle, domain, memtype);
+ }
+ break;
+
+ case '#':
+ /* Method (class & fn) type. */
+ if (**pp == '#')
+ {
+ debug_type return_type;
+
+ ++*pp;
+ return_type = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (return_type == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+ dtype = debug_make_method_type (dhandle, return_type,
+ DEBUG_TYPE_NULL,
+ (debug_type *) NULL, false);
+ }
+ else
+ {
+ debug_type domain;
+ debug_type return_type;
+ debug_type *args;
+ unsigned int n;
+ unsigned int alloc;
+ boolean varargs;
+
+ domain = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (domain == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ return_type = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (return_type == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ alloc = 10;
+ args = (debug_type *) xmalloc (alloc * sizeof *args);
+ n = 0;
+ while (**pp != ';')
+ {
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ if (n + 1 >= alloc)
+ {
+ alloc += 10;
+ args = ((debug_type *)
+ xrealloc ((PTR) args, alloc * sizeof *args));
+ }
+
+ args[n] = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (args[n] == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+ ++n;
+ }
+ ++*pp;
+
+ /* If the last type is not void, then this function takes a
+ variable number of arguments. Otherwise, we must strip
+ the void type. */
+ if (n == 0
+ || debug_get_type_kind (dhandle, args[n - 1]) != DEBUG_KIND_VOID)
+ varargs = true;
+ else
+ {
+ --n;
+ varargs = false;
+ }
+
+ args[n] = DEBUG_TYPE_NULL;
+
+ dtype = debug_make_method_type (dhandle, return_type, domain, args,
+ varargs);
+ }
+ break;
+
+ case 'r':
+ /* Range type. */
+ dtype = parse_stab_range_type (dhandle, info, typename, pp, typenums);
+ break;
+
+ case 'b':
+ /* FIXME: gdb checks os9k_stabs here. */
+ /* Sun ACC builtin int type. */
+ dtype = parse_stab_sun_builtin_type (dhandle, pp);
+ break;
+
+ case 'R':
+ /* Sun ACC builtin float type. */
+ dtype = parse_stab_sun_floating_type (dhandle, pp);
+ break;
+
+ case 'e':
+ /* Enumeration type. */
+ dtype = parse_stab_enum_type (dhandle, pp);
+ break;
+
+ case 's':
+ case 'u':
+ /* Struct or union type. */
+ dtype = parse_stab_struct_type (dhandle, info, typename, pp,
+ descriptor == 's', typenums);
+ break;
+
+ case 'a':
+ /* Array type. */
+ if (**pp != 'r')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ dtype = parse_stab_array_type (dhandle, info, pp, stringp);
+ break;
+
+ case 'S':
+ dtype = debug_make_set_type (dhandle,
+ parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
+ (debug_type **) NULL),
+ stringp);
+ break;
+
+ default:
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (dtype == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (typenums[0] != -1)
+ {
+ if (! stab_record_type (dhandle, info, typenums, dtype))
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (size != -1)
+ {
+ if (! debug_record_type_size (dhandle, dtype, (unsigned int) size))
+ return false;
+ }
+
+ return dtype;
+}
+
+/* Read a number by which a type is referred to in dbx data, or
+ perhaps read a pair (FILENUM, TYPENUM) in parentheses. Just a
+ single number N is equivalent to (0,N). Return the two numbers by
+ storing them in the vector TYPENUMS. */
+
+static boolean
+parse_stab_type_number (pp, typenums)
+ const char **pp;
+ int *typenums;
+{
+ const char *orig;
+
+ orig = *pp;
+
+ if (**pp != '(')
+ {
+ typenums[0] = 0;
+ typenums[1] = (int) parse_number (pp, (boolean *) NULL);
+ }
+ else
+ {
+ ++*pp;
+ typenums[0] = (int) parse_number (pp, (boolean *) NULL);
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+ typenums[1] = (int) parse_number (pp, (boolean *) NULL);
+ if (**pp != ')')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+ }
+
+ return true;
+}
+
+/* Parse a range type. */
+
+static debug_type
+parse_stab_range_type (dhandle, info, typename, pp, typenums)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *typename;
+ const char **pp;
+ const int *typenums;
+{
+ const char *orig;
+ int rangenums[2];
+ boolean self_subrange;
+ debug_type index_type;
+ const char *s2, *s3;
+ bfd_signed_vma n2, n3;
+ boolean ov2, ov3;
+
+ orig = *pp;
+
+ index_type = DEBUG_TYPE_NULL;
+
+ /* First comes a type we are a subrange of.
+ In C it is usually 0, 1 or the type being defined. */
+ if (! parse_stab_type_number (pp, rangenums))
+ return DEBUG_TYPE_NULL;
+
+ self_subrange = (rangenums[0] == typenums[0]
+ && rangenums[1] == typenums[1]);
+
+ if (**pp == '=')
+ {
+ *pp = orig;
+ index_type = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (index_type == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (**pp == ';')
+ ++*pp;
+
+ /* The remaining two operands are usually lower and upper bounds of
+ the range. But in some special cases they mean something else. */
+ s2 = *pp;
+ n2 = parse_number (pp, &ov2);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ s3 = *pp;
+ n3 = parse_number (pp, &ov3);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ if (ov2 || ov3)
+ {
+ /* gcc will emit range stabs for long long types. Handle this
+ as a special case. FIXME: This needs to be more general. */
+#define LLLOW "01000000000000000000000;"
+#define LLHIGH "0777777777777777777777;"
+#define ULLHIGH "01777777777777777777777;"
+ if (index_type == DEBUG_TYPE_NULL)
+ {
+ if (strncmp (s2, LLLOW, sizeof LLLOW - 1) == 0
+ && strncmp (s3, LLHIGH, sizeof LLHIGH - 1) == 0)
+ return debug_make_int_type (dhandle, 8, false);
+ if (! ov2
+ && n2 == 0
+ && strncmp (s3, ULLHIGH, sizeof ULLHIGH - 1) == 0)
+ return debug_make_int_type (dhandle, 8, true);
+ }
+
+ warn_stab (orig, "numeric overflow");
+ }
+
+ if (index_type == DEBUG_TYPE_NULL)
+ {
+ /* A type defined as a subrange of itself, with both bounds 0,
+ is void. */
+ if (self_subrange && n2 == 0 && n3 == 0)
+ return debug_make_void_type (dhandle);
+
+ /* A type defined as a subrange of itself, with n2 positive and
+ n3 zero, is a complex type, and n2 is the number of bytes. */
+ if (self_subrange && n3 == 0 && n2 > 0)
+ return debug_make_complex_type (dhandle, n2);
+
+ /* If n3 is zero and n2 is positive, this is a floating point
+ type, and n2 is the number of bytes. */
+ if (n3 == 0 && n2 > 0)
+ return debug_make_float_type (dhandle, n2);
+
+ /* If the upper bound is -1, this is an unsigned int. */
+ if (n2 == 0 && n3 == -1)
+ {
+ /* When gcc is used with -gstabs, but not -gstabs+, it will emit
+ long long int:t6=r1;0;-1;
+ long long unsigned int:t7=r1;0;-1;
+ We hack here to handle this reasonably. */
+ if (typename != NULL)
+ {
+ if (strcmp (typename, "long long int") == 0)
+ return debug_make_int_type (dhandle, 8, false);
+ else if (strcmp (typename, "long long unsigned int") == 0)
+ return debug_make_int_type (dhandle, 8, true);
+ }
+ /* FIXME: The size here really depends upon the target. */
+ return debug_make_int_type (dhandle, 4, true);
+ }
+
+ /* A range of 0 to 127 is char. */
+ if (self_subrange && n2 == 0 && n3 == 127)
+ return debug_make_int_type (dhandle, 1, false);
+
+ /* FIXME: gdb checks for the language CHILL here. */
+
+ if (n2 == 0)
+ {
+ if (n3 < 0)
+ return debug_make_int_type (dhandle, - n3, true);
+ else if (n3 == 0xff)
+ return debug_make_int_type (dhandle, 1, true);
+ else if (n3 == 0xffff)
+ return debug_make_int_type (dhandle, 2, true);
+ /* -1 is used for the upper bound of (4 byte) "unsigned int"
+ and "unsigned long", and we already checked for that, so
+ don't need to test for it here. */
+ }
+ else if (n3 == 0
+ && n2 < 0
+ && (self_subrange || n2 == -8))
+ return debug_make_int_type (dhandle, - n2, true);
+ else if (n2 == - n3 - 1)
+ {
+ if (n3 == 0x7f)
+ return debug_make_int_type (dhandle, 1, false);
+ else if (n3 == 0x7fff)
+ return debug_make_int_type (dhandle, 2, false);
+ else if (n3 == 0x7fffffff)
+ return debug_make_int_type (dhandle, 4, false);
+ }
+ }
+
+ /* At this point I don't have the faintest idea how to deal with a
+ self_subrange type; I'm going to assume that this is used as an
+ idiom, and that all of them are special cases. So . . . */
+ if (self_subrange)
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+
+ index_type = stab_find_type (dhandle, info, rangenums);
+ if (index_type == DEBUG_TYPE_NULL)
+ {
+ /* Does this actually ever happen? Is that why we are worrying
+ about dealing with it rather than just calling error_type? */
+ warn_stab (orig, "missing index type");
+ index_type = debug_make_int_type (dhandle, 4, false);
+ }
+
+ return debug_make_range_type (dhandle, index_type, n2, n3);
+}
+
+/* Sun's ACC uses a somewhat saner method for specifying the builtin
+ typedefs in every file (for int, long, etc):
+
+ type = b <signed> <width>; <offset>; <nbits>
+ signed = u or s. Possible c in addition to u or s (for char?).
+ offset = offset from high order bit to start bit of type.
+ width is # bytes in object of this type, nbits is # bits in type.
+
+ The width/offset stuff appears to be for small objects stored in
+ larger ones (e.g. `shorts' in `int' registers). We ignore it for now,
+ FIXME. */
+
+static debug_type
+parse_stab_sun_builtin_type (dhandle, pp)
+ PTR dhandle;
+ const char **pp;
+{
+ const char *orig;
+ boolean unsignedp;
+ bfd_vma bits;
+
+ orig = *pp;
+
+ switch (**pp)
+ {
+ case 's':
+ unsignedp = false;
+ break;
+ case 'u':
+ unsignedp = true;
+ break;
+ default:
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ /* For some odd reason, all forms of char put a c here. This is strange
+ because no other type has this honor. We can safely ignore this because
+ we actually determine 'char'acterness by the number of bits specified in
+ the descriptor. */
+ if (**pp == 'c')
+ ++*pp;
+
+ /* The first number appears to be the number of bytes occupied
+ by this type, except that unsigned short is 4 instead of 2.
+ Since this information is redundant with the third number,
+ we will ignore it. */
+ (void) parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ /* The second number is always 0, so ignore it too. */
+ (void) parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ /* The third number is the number of bits for this type. */
+ bits = parse_number (pp, (boolean *) NULL);
+
+ /* The type *should* end with a semicolon. If it are embedded
+ in a larger type the semicolon may be the only way to know where
+ the type ends. If this type is at the end of the stabstring we
+ can deal with the omitted semicolon (but we don't have to like
+ it). Don't bother to complain(), Sun's compiler omits the semicolon
+ for "void". */
+ if (**pp == ';')
+ ++*pp;
+
+ if (bits == 0)
+ return debug_make_void_type (dhandle);
+
+ return debug_make_int_type (dhandle, bits / 8, unsignedp);
+}
+
+/* Parse a builtin floating type generated by the Sun compiler. */
+
+static debug_type
+parse_stab_sun_floating_type (dhandle, pp)
+ PTR dhandle;
+ const char **pp;
+{
+ const char *orig;
+ bfd_vma details;
+ bfd_vma bytes;
+
+ orig = *pp;
+
+ /* The first number has more details about the type, for example
+ FN_COMPLEX. */
+ details = parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+
+ /* The second number is the number of bytes occupied by this type */
+ bytes = parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (details == NF_COMPLEX
+ || details == NF_COMPLEX16
+ || details == NF_COMPLEX32)
+ return debug_make_complex_type (dhandle, bytes);
+
+ return debug_make_float_type (dhandle, bytes);
+}
+
+/* Handle an enum type. */
+
+static debug_type
+parse_stab_enum_type (dhandle, pp)
+ PTR dhandle;
+ const char **pp;
+{
+ const char *orig;
+ const char **names;
+ bfd_signed_vma *values;
+ unsigned int n;
+ unsigned int alloc;
+
+ orig = *pp;
+
+ /* FIXME: gdb checks os9k_stabs here. */
+
+ /* The aix4 compiler emits an extra field before the enum members;
+ my guess is it's a type of some sort. Just ignore it. */
+ if (**pp == '-')
+ {
+ while (**pp != ':')
+ ++*pp;
+ ++*pp;
+ }
+
+ /* Read the value-names and their values.
+ The input syntax is NAME:VALUE,NAME:VALUE, and so on.
+ A semicolon or comma instead of a NAME means the end. */
+ alloc = 10;
+ names = (const char **) xmalloc (alloc * sizeof *names);
+ values = (bfd_signed_vma *) xmalloc (alloc * sizeof *values);
+ n = 0;
+ while (**pp != '\0' && **pp != ';' && **pp != ',')
+ {
+ const char *p;
+ char *name;
+ bfd_signed_vma val;
+
+ p = *pp;
+ while (*p != ':')
+ ++p;
+
+ name = savestring (*pp, p - *pp);
+
+ *pp = p + 1;
+ val = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ if (n + 1 >= alloc)
+ {
+ alloc += 10;
+ names = ((const char **)
+ xrealloc ((PTR) names, alloc * sizeof *names));
+ values = ((bfd_signed_vma *)
+ xrealloc ((PTR) values, alloc * sizeof *values));
+ }
+
+ names[n] = name;
+ values[n] = val;
+ ++n;
+ }
+
+ names[n] = NULL;
+ values[n] = 0;
+
+ if (**pp == ';')
+ ++*pp;
+
+ return debug_make_enum_type (dhandle, names, values);
+}
+
+/* Read the description of a structure (or union type) and return an object
+ describing the type.
+
+ PP points to a character pointer that points to the next unconsumed token
+ in the the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;",
+ *PP will point to "4a:1,0,32;;". */
+
+static debug_type
+parse_stab_struct_type (dhandle, info, tagname, pp, structp, typenums)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *tagname;
+ const char **pp;
+ boolean structp;
+ const int *typenums;
+{
+ const char *orig;
+ bfd_vma size;
+ debug_baseclass *baseclasses;
+ debug_field *fields;
+ boolean statics;
+ debug_method *methods;
+ debug_type vptrbase;
+ boolean ownvptr;
+
+ orig = *pp;
+
+ /* Get the size. */
+ size = parse_number (pp, (boolean *) NULL);
+
+ /* Get the other information. */
+ if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses)
+ || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics)
+ || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods)
+ || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase,
+ &ownvptr))
+ return DEBUG_TYPE_NULL;
+
+ if (! statics
+ && baseclasses == NULL
+ && methods == NULL
+ && vptrbase == DEBUG_TYPE_NULL
+ && ! ownvptr)
+ return debug_make_struct_type (dhandle, structp, size, fields);
+
+ return debug_make_object_type (dhandle, structp, size, fields, baseclasses,
+ methods, vptrbase, ownvptr);
+}
+
+/* The stabs for C++ derived classes contain baseclass information which
+ is marked by a '!' character after the total size. This function is
+ called when we encounter the baseclass marker, and slurps up all the
+ baseclass information.
+
+ Immediately following the '!' marker is the number of base classes that
+ the class is derived from, followed by information for each base class.
+ For each base class, there are two visibility specifiers, a bit offset
+ to the base class information within the derived class, a reference to
+ the type for the base class, and a terminating semicolon.
+
+ A typical example, with two base classes, would be "!2,020,19;0264,21;".
+ ^^ ^ ^ ^ ^ ^ ^
+ Baseclass information marker __________________|| | | | | | |
+ Number of baseclasses __________________________| | | | | | |
+ Visibility specifiers (2) ________________________| | | | | |
+ Offset in bits from start of class _________________| | | | |
+ Type number for base class ___________________________| | | |
+ Visibility specifiers (2) _______________________________| | |
+ Offset in bits from start of class ________________________| |
+ Type number of base class ____________________________________|
+
+ Return true for success, false for failure. */
+
+static boolean
+parse_stab_baseclasses (dhandle, info, pp, retp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ debug_baseclass **retp;
+{
+ const char *orig;
+ unsigned int c, i;
+ debug_baseclass *classes;
+
+ *retp = NULL;
+
+ orig = *pp;
+
+ if (**pp != '!')
+ {
+ /* No base classes. */
+ return true;
+ }
+ ++*pp;
+
+ c = (unsigned int) parse_number (pp, (boolean *) NULL);
+
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ classes = (debug_baseclass *) xmalloc ((c + 1) * sizeof (**retp));
+
+ for (i = 0; i < c; i++)
+ {
+ boolean virtual;
+ enum debug_visibility visibility;
+ bfd_vma bitpos;
+ debug_type type;
+
+ switch (**pp)
+ {
+ case '0':
+ virtual = false;
+ break;
+ case '1':
+ virtual = true;
+ break;
+ default:
+ warn_stab (orig, "unknown virtual character for baseclass");
+ virtual = false;
+ break;
+ }
+ ++*pp;
+
+ switch (**pp)
+ {
+ case '0':
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ break;
+ case '1':
+ visibility = DEBUG_VISIBILITY_PROTECTED;
+ break;
+ case '2':
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+ default:
+ warn_stab (orig, "unknown visibility character for baseclass");
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+ }
+ ++*pp;
+
+ /* The remaining value is the bit offset of the portion of the
+ object corresponding to this baseclass. Always zero in the
+ absence of multiple inheritance. */
+ bitpos = parse_number (pp, (boolean *) NULL);
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual,
+ visibility);
+ if (classes[i] == DEBUG_BASECLASS_NULL)
+ return false;
+
+ if (**pp != ';')
+ return false;
+ ++*pp;
+ }
+
+ classes[i] = DEBUG_BASECLASS_NULL;
+
+ *retp = classes;
+
+ return true;
+}
+
+/* Read struct or class data fields. They have the form:
+
+ NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
+
+ At the end, we see a semicolon instead of a field.
+
+ In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
+ a static field.
+
+ The optional VISIBILITY is one of:
+
+ '/0' (VISIBILITY_PRIVATE)
+ '/1' (VISIBILITY_PROTECTED)
+ '/2' (VISIBILITY_PUBLIC)
+ '/9' (VISIBILITY_IGNORE)
+
+ or nothing, for C style fields with public visibility.
+
+ Returns 1 for success, 0 for failure. */
+
+static boolean
+parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ debug_field **retp;
+ boolean *staticsp;
+{
+ const char *orig;
+ const char *p;
+ debug_field *fields;
+ unsigned int c;
+ unsigned int alloc;
+
+ *retp = NULL;
+ *staticsp = false;
+
+ orig = *pp;
+
+ c = 0;
+ alloc = 10;
+ fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+ while (**pp != ';')
+ {
+ /* FIXME: gdb checks os9k_stabs here. */
+
+ p = *pp;
+
+ /* Add 1 to c to leave room for NULL pointer at end. */
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ fields = ((debug_field *)
+ xrealloc ((PTR) fields, alloc * sizeof *fields));
+ }
+
+ /* If it starts with CPLUS_MARKER it is a special abbreviation,
+ unless the CPLUS_MARKER is followed by an underscore, in
+ which case it is just the name of an anonymous type, which we
+ should handle like any other type name. We accept either '$'
+ or '.', because a field name can never contain one of these
+ characters except as a CPLUS_MARKER. */
+
+ if ((*p == '$' || *p == '.') && p[1] != '_')
+ {
+ ++*pp;
+ if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
+ return false;
+ ++c;
+ continue;
+ }
+
+ /* Look for the ':' that separates the field name from the field
+ values. Data members are delimited by a single ':', while member
+ functions are delimited by a pair of ':'s. When we hit the member
+ functions (if any), terminate scan loop and return. */
+
+ p = strchr (p, ':');
+ if (p == NULL)
+ {
+ bad_stab (orig);
+ return false;
+ }
+
+ if (p[1] == ':')
+ break;
+
+ if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c,
+ staticsp))
+ return false;
+
+ ++c;
+ }
+
+ fields[c] = DEBUG_FIELD_NULL;
+
+ *retp = fields;
+
+ return true;
+}
+
+/* Special GNU C++ name. */
+
+static boolean
+parse_stab_cpp_abbrev (dhandle, info, pp, retp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ debug_field *retp;
+{
+ const char *orig;
+ int cpp_abbrev;
+ debug_type context;
+ const char *name;
+ const char *typename;
+ debug_type type;
+ bfd_vma bitpos;
+
+ *retp = DEBUG_FIELD_NULL;
+
+ orig = *pp;
+
+ if (**pp != 'v')
+ {
+ bad_stab (*pp);
+ return false;
+ }
+ ++*pp;
+
+ cpp_abbrev = **pp;
+ ++*pp;
+
+ /* At this point, *pp points to something like "22:23=*22...", where
+ the type number before the ':' is the "context" and everything
+ after is a regular type definition. Lookup the type, find it's
+ name, and construct the field name. */
+
+ context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (context == DEBUG_TYPE_NULL)
+ return false;
+
+ switch (cpp_abbrev)
+ {
+ case 'f':
+ /* $vf -- a virtual function table pointer. */
+ name = "_vptr$";
+ break;
+ case 'b':
+ /* $vb -- a virtual bsomethingorother */
+ typename = debug_get_type_name (dhandle, context);
+ if (typename == NULL)
+ {
+ warn_stab (orig, "unnamed $vb type");
+ typename = "FOO";
+ }
+ name = concat ("_vb$", typename, (const char *) NULL);
+ break;
+ default:
+ warn_stab (orig, "unrecognized C++ abbreviation");
+ name = "INVALID_CPLUSPLUS_ABBREV";
+ break;
+ }
+
+ if (**pp != ':')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ bitpos = parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ *retp = debug_make_field (dhandle, name, type, bitpos, 0,
+ DEBUG_VISIBILITY_PRIVATE);
+ if (*retp == DEBUG_FIELD_NULL)
+ return false;
+
+ return true;
+}
+
+/* Parse a single field in a struct or union. */
+
+static boolean
+parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ const char *p;
+ debug_field *retp;
+ boolean *staticsp;
+{
+ const char *orig;
+ char *name;
+ enum debug_visibility visibility;
+ debug_type type;
+ bfd_vma bitpos;
+ bfd_vma bitsize;
+
+ orig = *pp;
+
+ /* FIXME: gdb checks ARM_DEMANGLING here. */
+
+ name = savestring (*pp, p - *pp);
+
+ *pp = p + 1;
+
+ if (**pp != '/')
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ else
+ {
+ ++*pp;
+ switch (**pp)
+ {
+ case '0':
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ break;
+ case '1':
+ visibility = DEBUG_VISIBILITY_PROTECTED;
+ break;
+ case '2':
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+ default:
+ warn_stab (orig, "unknown visibility character for field");
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+ }
+ ++*pp;
+ }
+
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ if (**pp == ':')
+ {
+ char *varname;
+
+ /* This is a static class member. */
+ ++*pp;
+ p = strchr (*pp, ';');
+ if (p == NULL)
+ {
+ bad_stab (orig);
+ return false;
+ }
+
+ varname = savestring (*pp, p - *pp);
+
+ *pp = p + 1;
+
+ *retp = debug_make_static_member (dhandle, name, type, varname,
+ visibility);
+ *staticsp = true;
+
+ return true;
+ }
+
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ bitpos = parse_number (pp, (boolean *) NULL);
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ bitsize = parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ if (bitpos == 0 && bitsize == 0)
+ {
+ /* This can happen in two cases: (1) at least for gcc 2.4.5 or
+ so, it is a field which has been optimized out. The correct
+ stab for this case is to use VISIBILITY_IGNORE, but that is a
+ recent invention. (2) It is a 0-size array. For example
+ union { int num; char str[0]; } foo. Printing "<no value>"
+ for str in "p foo" is OK, since foo.str (and thus foo.str[3])
+ will continue to work, and a 0-size array as a whole doesn't
+ have any contents to print.
+
+ I suspect this probably could also happen with gcc -gstabs
+ (not -gstabs+) for static fields, and perhaps other C++
+ extensions. Hopefully few people use -gstabs with gdb, since
+ it is intended for dbx compatibility. */
+ visibility = DEBUG_VISIBILITY_IGNORE;
+ }
+
+ /* FIXME: gdb does some stuff here to mark fields as unpacked. */
+
+ *retp = debug_make_field (dhandle, name, type, bitpos, bitsize, visibility);
+
+ return true;
+}
+
+/* Read member function stabs info for C++ classes. The form of each member
+ function data is:
+
+ NAME :: TYPENUM[=type definition] ARGS : PHYSNAME ;
+
+ An example with two member functions is:
+
+ afunc1::20=##15;:i;2A.;afunc2::20:i;2A.;
+
+ For the case of overloaded operators, the format is op$::*.funcs, where
+ $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator
+ name (such as `+=') and `.' marks the end of the operator name. */
+
+static boolean
+parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *tagname;
+ const char **pp;
+ const int *typenums;
+ debug_method **retp;
+{
+ const char *orig;
+ debug_method *methods;
+ unsigned int c;
+ unsigned int alloc;
+
+ *retp = NULL;
+
+ orig = *pp;
+
+ alloc = 0;
+ methods = NULL;
+ c = 0;
+
+ while (**pp != ';')
+ {
+ const char *p;
+ char *name;
+ debug_method_variant *variants;
+ unsigned int cvars;
+ unsigned int allocvars;
+ debug_type look_ahead_type;
+
+ p = strchr (*pp, ':');
+ if (p == NULL || p[1] != ':')
+ break;
+
+ /* FIXME: Some systems use something other than '$' here. */
+ if ((*pp)[0] != 'o' || (*pp)[1] != 'p' || (*pp)[2] != '$')
+ {
+ name = savestring (*pp, p - *pp);
+ *pp = p + 2;
+ }
+ else
+ {
+ /* This is a completely wierd case. In order to stuff in the
+ names that might contain colons (the usual name delimiter),
+ Mike Tiemann defined a different name format which is
+ signalled if the identifier is "op$". In that case, the
+ format is "op$::XXXX." where XXXX is the name. This is
+ used for names like "+" or "=". YUUUUUUUK! FIXME! */
+ *pp = p + 2;
+ for (p = *pp; *p != '.' && *p != '\0'; p++)
+ ;
+ if (*p != '.')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ name = savestring (*pp, p - *pp);
+ *pp = p + 1;
+ }
+
+ allocvars = 10;
+ variants = ((debug_method_variant *)
+ xmalloc (allocvars * sizeof *variants));
+ cvars = 0;
+
+ look_ahead_type = DEBUG_TYPE_NULL;
+
+ do
+ {
+ debug_type type;
+ boolean stub;
+ char *argtypes;
+ enum debug_visibility visibility;
+ boolean constp, volatilep, staticp;
+ bfd_vma voffset;
+ debug_type context;
+ const char *physname;
+ boolean varargs;
+
+ if (look_ahead_type != DEBUG_TYPE_NULL)
+ {
+ /* g++ version 1 kludge */
+ type = look_ahead_type;
+ look_ahead_type = DEBUG_TYPE_NULL;
+ }
+ else
+ {
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+ if (**pp != ':')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ }
+
+ ++*pp;
+ p = strchr (*pp, ';');
+ if (p == NULL)
+ {
+ bad_stab (orig);
+ return false;
+ }
+
+ stub = false;
+ if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
+ && debug_get_parameter_types (dhandle, type, &varargs) == NULL)
+ stub = true;
+
+ argtypes = savestring (*pp, p - *pp);
+ *pp = p + 1;
+
+ switch (**pp)
+ {
+ case '0':
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ break;
+ case '1':
+ visibility = DEBUG_VISIBILITY_PROTECTED;
+ break;
+ default:
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+ }
+ ++*pp;
+
+ constp = false;
+ volatilep = false;
+ switch (**pp)
+ {
+ case 'A':
+ /* Normal function. */
+ ++*pp;
+ break;
+ case 'B':
+ /* const member function. */
+ constp = true;
+ ++*pp;
+ break;
+ case 'C':
+ /* volatile member function. */
+ volatilep = true;
+ ++*pp;
+ break;
+ case 'D':
+ /* const volatile member function. */
+ constp = true;
+ volatilep = true;
+ ++*pp;
+ break;
+ case '*':
+ case '?':
+ case '.':
+ /* File compiled with g++ version 1; no information. */
+ break;
+ default:
+ warn_stab (orig, "const/volatile indicator missing");
+ break;
+ }
+
+ staticp = false;
+ switch (**pp)
+ {
+ case '*':
+ /* virtual member function, followed by index. The sign
+ bit is supposedly set to distinguish
+ pointers-to-methods from virtual function indicies. */
+ ++*pp;
+ voffset = parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+ voffset &= 0x7fffffff;
+
+ if (**pp == ';' || *pp == '\0')
+ {
+ /* Must be g++ version 1. */
+ context = DEBUG_TYPE_NULL;
+ }
+ else
+ {
+ /* Figure out from whence this virtual function
+ came. It may belong to virtual function table of
+ one of its baseclasses. */
+ look_ahead_type = parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
+ (debug_type **) NULL);
+ if (**pp == ':')
+ {
+ /* g++ version 1 overloaded methods. */
+ }
+ else
+ {
+ context = look_ahead_type;
+ look_ahead_type = DEBUG_TYPE_NULL;
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+ }
+ }
+ break;
+
+ case '?':
+ /* static member function. */
+ ++*pp;
+ staticp = true;
+ voffset = 0;
+ context = DEBUG_TYPE_NULL;
+ if (strncmp (argtypes, name, strlen (name)) != 0)
+ stub = true;
+ break;
+
+ default:
+ warn_stab (orig, "member function type missing");
+ voffset = 0;
+ context = DEBUG_TYPE_NULL;
+ break;
+
+ case '.':
+ ++*pp;
+ voffset = 0;
+ context = DEBUG_TYPE_NULL;
+ break;
+ }
+
+ /* If the type is not a stub, then the argtypes string is
+ the physical name of the function. Otherwise the
+ argtypes string is the mangled form of the argument
+ types, and the full type and the physical name must be
+ extracted from them. */
+ if (! stub)
+ physname = argtypes;
+ else
+ {
+ debug_type class_type, return_type;
+
+ class_type = stab_find_type (dhandle, info, typenums);
+ if (class_type == DEBUG_TYPE_NULL)
+ return false;
+ return_type = debug_get_return_type (dhandle, type);
+ if (return_type == DEBUG_TYPE_NULL)
+ {
+ bad_stab (orig);
+ return false;
+ }
+ type = parse_stab_argtypes (dhandle, info, class_type, name,
+ tagname, return_type, argtypes,
+ constp, volatilep, &physname);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+ }
+
+ if (cvars + 1 >= allocvars)
+ {
+ allocvars += 10;
+ variants = ((debug_method_variant *)
+ xrealloc ((PTR) variants,
+ allocvars * sizeof *variants));
+ }
+
+ if (! staticp)
+ variants[cvars] = debug_make_method_variant (dhandle, physname,
+ type, visibility,
+ constp, volatilep,
+ voffset, context);
+ else
+ variants[cvars] = debug_make_static_method_variant (dhandle,
+ physname,
+ type,
+ visibility,
+ constp,
+ volatilep);
+ if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL)
+ return false;
+
+ ++cvars;
+ }
+ while (**pp != ';' && **pp != '\0');
+
+ variants[cvars] = DEBUG_METHOD_VARIANT_NULL;
+
+ if (**pp != '\0')
+ ++*pp;
+
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ methods = ((debug_method *)
+ xrealloc ((PTR) methods, alloc * sizeof *methods));
+ }
+
+ methods[c] = debug_make_method (dhandle, name, variants);
+
+ ++c;
+ }
+
+ if (methods != NULL)
+ methods[c] = DEBUG_METHOD_NULL;
+
+ *retp = methods;
+
+ return true;
+}
+
+/* Parse a string representing argument types for a method. Stabs
+ tries to save space by packing argument types into a mangled
+ string. This string should give us enough information to extract
+ both argument types and the physical name of the function, given
+ the tag name. */
+
+static debug_type
+parse_stab_argtypes (dhandle, info, class_type, fieldname, tagname,
+ return_type, argtypes, constp, volatilep, pphysname)
+ PTR dhandle;
+ struct stab_handle *info;
+ debug_type class_type;
+ const char *fieldname;
+ const char *tagname;
+ debug_type return_type;
+ const char *argtypes;
+ boolean constp;
+ boolean volatilep;
+ const char **pphysname;
+{
+ boolean is_full_physname_constructor;
+ boolean is_constructor;
+ boolean is_destructor;
+ debug_type *args;
+ boolean varargs;
+
+ /* Constructors are sometimes handled specially. */
+ is_full_physname_constructor = ((argtypes[0] == '_'
+ && argtypes[1] == '_'
+ && (isdigit ((unsigned char) argtypes[2])
+ || argtypes[2] == 'Q'
+ || argtypes[2] == 't'))
+ || strncmp (argtypes, "__ct", 4) == 0);
+
+ is_constructor = (is_full_physname_constructor
+ || (tagname != NULL
+ && strcmp (fieldname, tagname) == 0));
+ is_destructor = ((argtypes[0] == '_'
+ && (argtypes[1] == '$' || argtypes[1] == '.')
+ && argtypes[2] == '_')
+ || strncmp (argtypes, "__dt", 4) == 0);
+
+ if (is_destructor || is_full_physname_constructor)
+ *pphysname = argtypes;
+ else
+ {
+ unsigned int len;
+ const char *const_prefix;
+ const char *volatile_prefix;
+ char buf[20];
+ unsigned int mangled_name_len;
+ char *physname;
+
+ len = tagname == NULL ? 0 : strlen (tagname);
+ const_prefix = constp ? "C" : "";
+ volatile_prefix = volatilep ? "V" : "";
+
+ if (len == 0)
+ sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ else if (tagname != NULL && strchr (tagname, '<') != NULL)
+ {
+ /* Template methods are fully mangled. */
+ sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ tagname = NULL;
+ len = 0;
+ }
+ else
+ sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
+
+ mangled_name_len = ((is_constructor ? 0 : strlen (fieldname))
+ + strlen (buf)
+ + len
+ + strlen (argtypes)
+ + 1);
+
+ if (fieldname[0] == 'o'
+ && fieldname[1] == 'p'
+ && (fieldname[2] == '$' || fieldname[2] == '.'))
+ {
+ const char *opname;
+
+ opname = cplus_mangle_opname (fieldname + 3, 0);
+ if (opname == NULL)
+ {
+ fprintf (stderr, "No mangling for \"%s\"\n", fieldname);
+ return DEBUG_TYPE_NULL;
+ }
+ mangled_name_len += strlen (opname);
+ physname = (char *) xmalloc (mangled_name_len);
+ strncpy (physname, fieldname, 3);
+ strcpy (physname + 3, opname);
+ }
+ else
+ {
+ physname = (char *) xmalloc (mangled_name_len);
+ if (is_constructor)
+ physname[0] = '\0';
+ else
+ strcpy (physname, fieldname);
+ }
+
+ strcat (physname, buf);
+ if (tagname != NULL)
+ strcat (physname, tagname);
+ strcat (physname, argtypes);
+
+ *pphysname = physname;
+ }
+
+ if (*argtypes == '\0')
+ {
+ args = (debug_type *) xmalloc (sizeof *args);
+ *args = NULL;
+ return debug_make_method_type (dhandle, return_type, class_type, args,
+ false);
+ }
+
+ args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs);
+ if (args == NULL)
+ return DEBUG_TYPE_NULL;
+
+ return debug_make_method_type (dhandle, return_type, class_type, args,
+ varargs);
+}
+
+/* The tail end of stabs for C++ classes that contain a virtual function
+ pointer contains a tilde, a %, and a type number.
+ The type number refers to the base class (possibly this class itself) which
+ contains the vtable pointer for the current class.
+
+ This function is called when we have parsed all the method declarations,
+ so we can look for the vptr base class info. */
+
+static boolean
+parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ const int *typenums;
+ debug_type *retvptrbase;
+ boolean *retownvptr;
+{
+ const char *orig;
+ const char *hold;
+ int vtypenums[2];
+
+ *retvptrbase = DEBUG_TYPE_NULL;
+ *retownvptr = false;
+
+ orig = *pp;
+
+ /* If we are positioned at a ';', then skip it. */
+ if (**pp == ';')
+ ++*pp;
+
+ if (**pp != '~')
+ return true;
+
+ ++*pp;
+
+ if (**pp == '=' || **pp == '+' || **pp == '-')
+ {
+ /* Obsolete flags that used to indicate the presence of
+ constructors and/or destructors. */
+ ++*pp;
+ }
+
+ if (**pp != '%')
+ return true;
+
+ ++*pp;
+
+ hold = *pp;
+
+ /* The next number is the type number of the base class (possibly
+ our own class) which supplies the vtable for this class. */
+ if (! parse_stab_type_number (pp, vtypenums))
+ return false;
+
+ if (vtypenums[0] == typenums[0]
+ && vtypenums[1] == typenums[1])
+ *retownvptr = true;
+ else
+ {
+ debug_type vtype;
+ const char *p;
+
+ *pp = hold;
+
+ vtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ for (p = *pp; *p != ';' && *p != '\0'; p++)
+ ;
+ if (*p != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+
+ *retvptrbase = vtype;
+
+ *pp = p + 1;
+ }
+
+ return true;
+}
+
+/* Read a definition of an array type. */
+
+static debug_type
+parse_stab_array_type (dhandle, info, pp, stringp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ boolean stringp;
+{
+ const char *orig;
+ const char *p;
+ int typenums[2];
+ debug_type index_type;
+ boolean adjustable;
+ bfd_signed_vma lower, upper;
+ debug_type element_type;
+
+ /* Format of an array type:
+ "ar<index type>;lower;upper;<array_contents_type>".
+ OS9000: "arlower,upper;<array_contents_type>".
+
+ Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
+ for these, produce a type like float[][]. */
+
+ orig = *pp;
+
+ /* FIXME: gdb checks os9k_stabs here. */
+
+ /* If the index type is type 0, we take it as int. */
+ p = *pp;
+ if (! parse_stab_type_number (&p, typenums))
+ return false;
+ if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
+ {
+ index_type = debug_find_named_type (dhandle, "int");
+ if (index_type == DEBUG_TYPE_NULL)
+ {
+ index_type = debug_make_int_type (dhandle, 4, false);
+ if (index_type == DEBUG_TYPE_NULL)
+ return false;
+ }
+ *pp = p;
+ }
+ else
+ {
+ index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ }
+
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ adjustable = false;
+
+ if (! isdigit ((unsigned char) **pp) && **pp != '-')
+ {
+ ++*pp;
+ adjustable = true;
+ }
+
+ lower = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ if (! isdigit ((unsigned char) **pp) && **pp != '-')
+ {
+ ++*pp;
+ adjustable = true;
+ }
+
+ upper = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (element_type == DEBUG_TYPE_NULL)
+ return false;
+
+ if (adjustable)
+ {
+ lower = 0;
+ upper = -1;
+ }
+
+ return debug_make_array_type (dhandle, element_type, index_type, lower,
+ upper, stringp);
+}
+
+/* Keep a stack of N_BINCL include files. */
+
+struct bincl_file
+{
+ struct bincl_file *next;
+ const char *name;
+};
+
+/* Start a new N_BINCL file, pushing it onto the stack. */
+
+static void
+push_bincl (info, name)
+ struct stab_handle *info;
+ const char *name;
+{
+ struct bincl_file *n;
+
+ n = (struct bincl_file *) xmalloc (sizeof *n);
+ n->next = info->bincl_stack;
+ n->name = name;
+ info->bincl_stack = n;
+
+ ++info->files;
+ info->file_types = ((struct stab_types **)
+ xrealloc ((PTR) info->file_types,
+ (info->files
+ * sizeof *info->file_types)));
+ info->file_types[info->files - 1] = NULL;
+}
+
+/* Finish an N_BINCL file, at an N_EINCL, popping the name off the
+ stack. */
+
+static const char *
+pop_bincl (info)
+ struct stab_handle *info;
+{
+ struct bincl_file *o;
+
+ o = info->bincl_stack;
+ if (o == NULL)
+ return info->main_filename;
+ info->bincl_stack = o->next;
+ free (o);
+ if (info->bincl_stack == NULL)
+ return info->main_filename;
+ return info->bincl_stack->name;
+}
+
+/* Handle a variable definition. gcc emits variable definitions for a
+ block before the N_LBRAC, so we must hold onto them until we see
+ it. The SunPRO compiler emits variable definitions after the
+ N_LBRAC, so we can call debug_record_variable immediately. */
+
+static boolean
+stab_record_variable (dhandle, info, name, type, kind, val)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *name;
+ debug_type type;
+ enum debug_var_kind kind;
+ bfd_vma val;
+{
+ struct stab_pending_var *v;
+
+ if ((kind == DEBUG_GLOBAL || kind == DEBUG_STATIC)
+ || ! info->within_function
+ || (info->gcc_compiled == 0 && info->n_opt_found))
+ return debug_record_variable (dhandle, name, type, kind, val);
+
+ v = (struct stab_pending_var *) xmalloc (sizeof *v);
+ memset (v, 0, sizeof *v);
+
+ v->next = info->pending;
+ v->name = name;
+ v->type = type;
+ v->kind = kind;
+ v->val = val;
+ info->pending = v;
+
+ return true;
+}
+
+/* Emit pending variable definitions. This is called after we see the
+ N_LBRAC that starts the block. */
+
+static boolean
+stab_emit_pending_vars (dhandle, info)
+ PTR dhandle;
+ struct stab_handle *info;
+{
+ struct stab_pending_var *v;
+
+ v = info->pending;
+ while (v != NULL)
+ {
+ struct stab_pending_var *next;
+
+ if (! debug_record_variable (dhandle, v->name, v->type, v->kind, v->val))
+ return false;
+
+ next = v->next;
+ free (v);
+ v = next;
+ }
+
+ info->pending = NULL;
+
+ return true;
+}
+
+/* Find the slot for a type in the database. */
+
+static debug_type *
+stab_find_slot (info, typenums)
+ struct stab_handle *info;
+ const int *typenums;
+{
+ int filenum;
+ int index;
+ struct stab_types **ps;
+
+ filenum = typenums[0];
+ index = typenums[1];
+
+ if (filenum < 0 || (unsigned int) filenum >= info->files)
+ {
+ fprintf (stderr, "Type file number %d out of range\n", filenum);
+ return NULL;
+ }
+ if (index < 0)
+ {
+ fprintf (stderr, "Type index number %d out of range\n", index);
+ return NULL;
+ }
+
+ ps = info->file_types + filenum;
+
+ while (index >= STAB_TYPES_SLOTS)
+ {
+ if (*ps == NULL)
+ {
+ *ps = (struct stab_types *) xmalloc (sizeof **ps);
+ memset (*ps, 0, sizeof **ps);
+ }
+ ps = &(*ps)->next;
+ index -= STAB_TYPES_SLOTS;
+ }
+ if (*ps == NULL)
+ {
+ *ps = (struct stab_types *) xmalloc (sizeof **ps);
+ memset (*ps, 0, sizeof **ps);
+ }
+
+ return (*ps)->types + index;
+}
+
+/* Find a type given a type number. If the type has not been
+ allocated yet, create an indirect type. */
+
+static debug_type
+stab_find_type (dhandle, info, typenums)
+ PTR dhandle;
+ struct stab_handle *info;
+ const int *typenums;
+{
+ debug_type *slot;
+
+ if (typenums[0] == 0 && typenums[1] < 0)
+ {
+ /* A negative type number indicates an XCOFF builtin type. */
+ return stab_xcoff_builtin_type (dhandle, info, typenums[1]);
+ }
+
+ slot = stab_find_slot (info, typenums);
+ if (slot == NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (*slot == DEBUG_TYPE_NULL)
+ return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
+
+ return *slot;
+}
+
+/* Record that a given type number refers to a given type. */
+
+static boolean
+stab_record_type (dhandle, info, typenums, type)
+ PTR dhandle;
+ struct stab_handle *info;
+ const int *typenums;
+ debug_type type;
+{
+ debug_type *slot;
+
+ slot = stab_find_slot (info, typenums);
+ if (slot == NULL)
+ return false;
+
+ /* gdb appears to ignore type redefinitions, so we do as well. */
+
+ *slot = type;
+
+ return true;
+}
+
+/* Return an XCOFF builtin type. */
+
+static debug_type
+stab_xcoff_builtin_type (dhandle, info, typenum)
+ PTR dhandle;
+ struct stab_handle *info;
+ int typenum;
+{
+ debug_type rettype;
+ const char *name;
+
+ if (typenum >= 0 || typenum < -XCOFF_TYPE_COUNT)
+ {
+ fprintf (stderr, "Unrecognized XCOFF type %d\n", typenum);
+ return DEBUG_TYPE_NULL;
+ }
+ if (info->xcoff_types[-typenum] != NULL)
+ return info->xcoff_types[-typenum];
+
+ switch (-typenum)
+ {
+ case 1:
+ /* The size of this and all the other types are fixed, defined
+ by the debugging format. */
+ name = "int";
+ rettype = debug_make_int_type (dhandle, 4, false);
+ break;
+ case 2:
+ name = "char";
+ rettype = debug_make_int_type (dhandle, 1, false);
+ break;
+ case 3:
+ name = "short";
+ rettype = debug_make_int_type (dhandle, 2, false);
+ break;
+ case 4:
+ name = "long";
+ rettype = debug_make_int_type (dhandle, 4, false);
+ break;
+ case 5:
+ name = "unsigned char";
+ rettype = debug_make_int_type (dhandle, 1, true);
+ break;
+ case 6:
+ name = "signed char";
+ rettype = debug_make_int_type (dhandle, 1, false);
+ break;
+ case 7:
+ name = "unsigned short";
+ rettype = debug_make_int_type (dhandle, 2, true);
+ break;
+ case 8:
+ name = "unsigned int";
+ rettype = debug_make_int_type (dhandle, 4, true);
+ break;
+ case 9:
+ name = "unsigned";
+ rettype = debug_make_int_type (dhandle, 4, true);
+ case 10:
+ name = "unsigned long";
+ rettype = debug_make_int_type (dhandle, 4, true);
+ break;
+ case 11:
+ name = "void";
+ rettype = debug_make_void_type (dhandle);
+ break;
+ case 12:
+ /* IEEE single precision (32 bit). */
+ name = "float";
+ rettype = debug_make_float_type (dhandle, 4);
+ break;
+ case 13:
+ /* IEEE double precision (64 bit). */
+ name = "double";
+ rettype = debug_make_float_type (dhandle, 8);
+ break;
+ case 14:
+ /* This is an IEEE double on the RS/6000, and different machines
+ with different sizes for "long double" should use different
+ negative type numbers. See stabs.texinfo. */
+ name = "long double";
+ rettype = debug_make_float_type (dhandle, 8);
+ break;
+ case 15:
+ name = "integer";
+ rettype = debug_make_int_type (dhandle, 4, false);
+ break;
+ case 16:
+ name = "boolean";
+ rettype = debug_make_bool_type (dhandle, 4);
+ break;
+ case 17:
+ name = "short real";
+ rettype = debug_make_float_type (dhandle, 4);
+ break;
+ case 18:
+ name = "real";
+ rettype = debug_make_float_type (dhandle, 8);
+ break;
+ case 19:
+ /* FIXME */
+ name = "stringptr";
+ rettype = NULL;
+ break;
+ case 20:
+ /* FIXME */
+ name = "character";
+ rettype = debug_make_int_type (dhandle, 1, true);
+ break;
+ case 21:
+ name = "logical*1";
+ rettype = debug_make_bool_type (dhandle, 1);
+ break;
+ case 22:
+ name = "logical*2";
+ rettype = debug_make_bool_type (dhandle, 2);
+ break;
+ case 23:
+ name = "logical*4";
+ rettype = debug_make_bool_type (dhandle, 4);
+ break;
+ case 24:
+ name = "logical";
+ rettype = debug_make_bool_type (dhandle, 4);
+ break;
+ case 25:
+ /* Complex type consisting of two IEEE single precision values. */
+ name = "complex";
+ rettype = debug_make_complex_type (dhandle, 8);
+ break;
+ case 26:
+ /* Complex type consisting of two IEEE double precision values. */
+ name = "double complex";
+ rettype = debug_make_complex_type (dhandle, 16);
+ break;
+ case 27:
+ name = "integer*1";
+ rettype = debug_make_int_type (dhandle, 1, false);
+ break;
+ case 28:
+ name = "integer*2";
+ rettype = debug_make_int_type (dhandle, 2, false);
+ break;
+ case 29:
+ name = "integer*4";
+ rettype = debug_make_int_type (dhandle, 4, false);
+ break;
+ case 30:
+ /* FIXME */
+ name = "wchar";
+ rettype = debug_make_int_type (dhandle, 2, false);
+ break;
+ case 31:
+ name = "long long";
+ rettype = debug_make_int_type (dhandle, 8, false);
+ break;
+ case 32:
+ name = "unsigned long long";
+ rettype = debug_make_int_type (dhandle, 8, true);
+ break;
+ case 33:
+ name = "logical*8";
+ rettype = debug_make_bool_type (dhandle, 8);
+ break;
+ case 34:
+ name = "integer*8";
+ rettype = debug_make_int_type (dhandle, 8, false);
+ break;
+ default:
+ abort ();
+ }
+
+ rettype = debug_name_type (dhandle, name, rettype);
+
+ info->xcoff_types[-typenum] = rettype;
+
+ return rettype;
+}
+
+/* Find or create a tagged type. */
+
+static debug_type
+stab_find_tagged_type (dhandle, info, p, len, kind)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *p;
+ int len;
+ enum debug_type_kind kind;
+{
+ char *name;
+ debug_type dtype;
+ struct stab_tag *st;
+
+ name = savestring (p, len);
+
+ /* We pass DEBUG_KIND_ILLEGAL because we want all tags in the same
+ namespace. This is right for C, and I don't know how to handle
+ other languages. FIXME. */
+ dtype = debug_find_tagged_type (dhandle, name, DEBUG_KIND_ILLEGAL);
+ if (dtype != DEBUG_TYPE_NULL)
+ {
+ free (name);
+ return dtype;
+ }
+
+ /* We need to allocate an entry on the undefined tag list. */
+ for (st = info->tags; st != NULL; st = st->next)
+ {
+ if (st->name[0] == name[0]
+ && strcmp (st->name, name) == 0)
+ {
+ if (st->kind == DEBUG_KIND_ILLEGAL)
+ st->kind = kind;
+ free (name);
+ break;
+ }
+ }
+ if (st == NULL)
+ {
+ st = (struct stab_tag *) xmalloc (sizeof *st);
+ memset (st, 0, sizeof *st);
+
+ st->next = info->tags;
+ st->name = name;
+ st->kind = kind;
+ st->slot = DEBUG_TYPE_NULL;
+ st->type = debug_make_indirect_type (dhandle, &st->slot, name);
+ info->tags = st;
+ }
+
+ return st->type;
+}
+
+/* In order to get the correct argument types for a stubbed method, we
+ need to extract the argument types from a C++ mangled string.
+ Since the argument types can refer back to the return type, this
+ means that we must demangle the entire physical name. In gdb this
+ is done by calling cplus_demangle and running the results back
+ through the C++ expression parser. Since we have no expression
+ parser, we must duplicate much of the work of cplus_demangle here.
+
+ We assume that GNU style demangling is used, since this is only
+ done for method stubs, and only g++ should output that form of
+ debugging information. */
+
+/* This structure is used to hold a pointer to type information which
+ demangling a string. */
+
+struct stab_demangle_typestring
+{
+ /* The start of the type. This is not null terminated. */
+ const char *typestring;
+ /* The length of the type. */
+ unsigned int len;
+};
+
+/* This structure is used to hold information while demangling a
+ string. */
+
+struct stab_demangle_info
+{
+ /* The debugging information handle. */
+ PTR dhandle;
+ /* The stab information handle. */
+ struct stab_handle *info;
+ /* The array of arguments we are building. */
+ debug_type *args;
+ /* Whether the method takes a variable number of arguments. */
+ boolean varargs;
+ /* The array of types we have remembered. */
+ struct stab_demangle_typestring *typestrings;
+ /* The number of typestrings. */
+ unsigned int typestring_count;
+ /* The number of typestring slots we have allocated. */
+ unsigned int typestring_alloc;
+};
+
+static void stab_bad_demangle PARAMS ((const char *));
+static unsigned int stab_demangle_count PARAMS ((const char **));
+static boolean stab_demangle_get_count
+ PARAMS ((const char **, unsigned int *));
+static boolean stab_demangle_prefix
+ PARAMS ((struct stab_demangle_info *, const char **));
+static boolean stab_demangle_function_name
+ PARAMS ((struct stab_demangle_info *, const char **, const char *));
+static boolean stab_demangle_signature
+ PARAMS ((struct stab_demangle_info *, const char **));
+static boolean stab_demangle_qualified
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
+static boolean stab_demangle_template
+ PARAMS ((struct stab_demangle_info *, const char **));
+static boolean stab_demangle_class
+ PARAMS ((struct stab_demangle_info *, const char **, const char **));
+static boolean stab_demangle_args
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
+ boolean *));
+static boolean stab_demangle_arg
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
+ unsigned int *, unsigned int *));
+static boolean stab_demangle_type
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
+static boolean stab_demangle_fund_type
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
+static boolean stab_demangle_remember_type
+ PARAMS ((struct stab_demangle_info *, const char *, int));
+
+/* Warn about a bad demangling. */
+
+static void
+stab_bad_demangle (s)
+ const char *s;
+{
+ fprintf (stderr, "bad mangled name `%s'\n", s);
+}
+
+/* Get a count from a stab string. */
+
+static unsigned int
+stab_demangle_count (pp)
+ const char **pp;
+{
+ unsigned int count;
+
+ count = 0;
+ while (isdigit ((unsigned char) **pp))
+ {
+ count *= 10;
+ count += **pp - '0';
+ ++*pp;
+ }
+ return count;
+}
+
+/* Require a count in a string. The count may be multiple digits, in
+ which case it must end in an underscore. */
+
+static boolean
+stab_demangle_get_count (pp, pi)
+ const char **pp;
+ unsigned int *pi;
+{
+ if (! isdigit ((unsigned char) **pp))
+ return false;
+
+ *pi = **pp - '0';
+ ++*pp;
+ if (isdigit ((unsigned char) **pp))
+ {
+ unsigned int count;
+ const char *p;
+
+ count = *pi;
+ p = *pp;
+ do
+ {
+ count *= 10;
+ count += *p - '0';
+ ++p;
+ }
+ while (isdigit ((unsigned char) *p));
+ if (*p == '_')
+ {
+ *pp = p + 1;
+ *pi = count;
+ }
+ }
+
+ return true;
+}
+
+/* This function demangles a physical name, returning a NULL
+ terminated array of argument types. */
+
+static debug_type *
+stab_demangle_argtypes (dhandle, info, physname, pvarargs)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *physname;
+ boolean *pvarargs;
+{
+ struct stab_demangle_info minfo;
+
+ minfo.dhandle = dhandle;
+ minfo.info = info;
+ minfo.args = NULL;
+ minfo.varargs = false;
+ minfo.typestring_alloc = 10;
+ minfo.typestrings = ((struct stab_demangle_typestring *)
+ xmalloc (minfo.typestring_alloc
+ * sizeof *minfo.typestrings));
+ minfo.typestring_count = 0;
+
+ /* cplus_demangle checks for special GNU mangled forms, but we can't
+ see any of them in mangled method argument types. */
+
+ if (! stab_demangle_prefix (&minfo, &physname))
+ goto error_return;
+
+ if (*physname != '\0')
+ {
+ if (! stab_demangle_signature (&minfo, &physname))
+ goto error_return;
+ }
+
+ free (minfo.typestrings);
+ minfo.typestrings = NULL;
+
+ if (minfo.args == NULL)
+ fprintf (stderr, "no argument types in mangled string\n");
+
+ *pvarargs = minfo.varargs;
+ return minfo.args;
+
+ error_return:
+ if (minfo.typestrings != NULL)
+ free (minfo.typestrings);
+ return NULL;
+}
+
+/* Demangle the prefix of the mangled name. */
+
+static boolean
+stab_demangle_prefix (minfo, pp)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+{
+ const char *scan;
+ unsigned int i;
+
+ /* cplus_demangle checks for global constructors and destructors,
+ but we can't see them in mangled argument types. */
+
+ /* Look for `__'. */
+ scan = *pp;
+ do
+ {
+ scan = strchr (scan, '_');
+ }
+ while (scan != NULL && *++scan != '_');
+
+ if (scan == NULL)
+ {
+ stab_bad_demangle (*pp);
+ return false;
+ }
+
+ --scan;
+
+ /* We found `__'; move ahead to the last contiguous `__' pair. */
+ i = strspn (scan, "_");
+ if (i > 2)
+ scan += i - 2;
+
+ if (scan == *pp
+ && (isdigit ((unsigned char) scan[2])
+ || scan[2] == 'Q'
+ || scan[2] == 't'))
+ {
+ /* This is a GNU style constructor name. */
+ *pp = scan + 2;
+ return true;
+ }
+ else if (scan == *pp
+ && ! isdigit ((unsigned char) scan[2])
+ && scan[2] != 't')
+ {
+ /* Look for the `__' that separates the prefix from the
+ signature. */
+ while (*scan == '_')
+ ++scan;
+ scan = strstr (scan, "__");
+ if (scan == NULL || scan[2] == '\0')
+ {
+ stab_bad_demangle (*pp);
+ return false;
+ }
+
+ return stab_demangle_function_name (minfo, pp, scan);
+ }
+ else if (scan[2] != '\0')
+ {
+ /* The name doesn't start with `__', but it does contain `__'. */
+ return stab_demangle_function_name (minfo, pp, scan);
+ }
+ else
+ {
+ stab_bad_demangle (*pp);
+ return false;
+ }
+ /*NOTREACHED*/
+}
+
+/* Demangle a function name prefix. The scan argument points to the
+ double underscore which separates the function name from the
+ signature. */
+
+static boolean
+stab_demangle_function_name (minfo, pp, scan)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ const char *scan;
+{
+ const char *name;
+
+ /* The string from *pp to scan is the name of the function. We
+ don't care about the name, since we just looking for argument
+ types. However, for conversion operators, the name may include a
+ type which we must remember in order to handle backreferences. */
+
+ name = *pp;
+ *pp = scan + 2;
+
+ if (*pp - name >= 5
+ && strncmp (name, "type", 4) == 0
+ && (name[4] == '$' || name[4] == '.'))
+ {
+ const char *tem;
+
+ /* This is a type conversion operator. */
+ tem = name + 5;
+ if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
+ return false;
+ }
+ else if (name[0] == '_'
+ && name[1] == '_'
+ && name[2] == 'o'
+ && name[3] == 'p')
+ {
+ const char *tem;
+
+ /* This is a type conversion operator. */
+ tem = name + 4;
+ if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
+ return false;
+ }
+
+ return true;
+}
+
+/* Demangle the signature. This is where the argument types are
+ found. */
+
+static boolean
+stab_demangle_signature (minfo, pp)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+{
+ const char *orig;
+ boolean expect_func, func_done;
+ const char *hold;
+
+ orig = *pp;
+
+ expect_func = false;
+ func_done = false;
+ hold = NULL;
+
+ while (**pp != '\0')
+ {
+ switch (**pp)
+ {
+ case 'Q':
+ hold = *pp;
+ if (! stab_demangle_qualified (minfo, pp, (debug_type *) NULL)
+ || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+ return false;
+ expect_func = true;
+ hold = NULL;
+ break;
+
+ case 'S':
+ /* Static member function. FIXME: Can this happen? */
+ if (hold == NULL)
+ hold = *pp;
+ ++*pp;
+ break;
+
+ case 'C':
+ /* Const member function. */
+ if (hold == NULL)
+ hold = *pp;
+ ++*pp;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (hold == NULL)
+ hold = *pp;
+ if (! stab_demangle_class (minfo, pp, (const char **) NULL)
+ || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+ return false;
+ expect_func = true;
+ hold = NULL;
+ break;
+
+ case 'F':
+ /* Function. I don't know if this actually happens with g++
+ output. */
+ hold = NULL;
+ func_done = true;
+ ++*pp;
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+ return false;
+ break;
+
+ case 't':
+ /* Template. */
+ if (hold == NULL)
+ hold = *pp;
+ if (! stab_demangle_template (minfo, pp)
+ || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+ return false;
+ hold = NULL;
+ expect_func = true;
+ break;
+
+ case '_':
+ /* At the outermost level, we cannot have a return type
+ specified, so if we run into another '_' at this point we
+ are dealing with a mangled name that is either bogus, or
+ has been mangled by some algorithm we don't know how to
+ deal with. So just reject the entire demangling. */
+ stab_bad_demangle (orig);
+ return false;
+
+ default:
+ /* Assume we have stumbled onto the first outermost function
+ argument token, and start processing args. */
+ func_done = true;
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+ return false;
+ break;
+ }
+
+ if (expect_func)
+ {
+ func_done = true;
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+ return false;
+ }
+ }
+
+ if (! func_done)
+ {
+ /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
+ bar__3fooi is 'foo::bar(int)'. We get here when we find the
+ first case, and need to ensure that the '(void)' gets added
+ to the current declp. */
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+ return false;
+ }
+
+ return true;
+}
+
+/* Demangle a qualified name, such as "Q25Outer5Inner" which is the
+ mangled form of "Outer::Inner". */
+
+static boolean
+stab_demangle_qualified (minfo, pp, ptype)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ debug_type *ptype;
+{
+ const char *orig;
+ const char *p;
+ unsigned int qualifiers;
+ debug_type context;
+
+ orig = *pp;
+
+ switch ((*pp)[1])
+ {
+ case '_':
+ /* GNU mangled name with more than 9 classes. The count is
+ preceded by an underscore (to distinguish it from the <= 9
+ case) and followed by an underscore. */
+ p = *pp + 2;
+ if (! isdigit ((unsigned char) *p) || *p == '0')
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ qualifiers = atoi (p);
+ while (isdigit ((unsigned char) *p))
+ ++p;
+ if (*p != '_')
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ *pp = p + 1;
+ break;
+
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ qualifiers = (*pp)[1] - '0';
+ /* Skip an optional underscore after the count. */
+ if ((*pp)[2] == '_')
+ ++*pp;
+ *pp += 2;
+ break;
+
+ case '0':
+ default:
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ context = DEBUG_TYPE_NULL;
+
+ /* Pick off the names. */
+ while (qualifiers-- > 0)
+ {
+ if (**pp == '_')
+ ++*pp;
+ if (**pp == 't')
+ {
+ /* FIXME: I don't know how to handle the ptype != NULL case
+ here. */
+ if (! stab_demangle_template (minfo, pp))
+ return false;
+ }
+ else
+ {
+ unsigned int len;
+
+ len = stab_demangle_count (pp);
+ if (strlen (*pp) < len)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ if (ptype != NULL)
+ {
+ const debug_field *fields;
+
+ fields = NULL;
+ if (context != DEBUG_TYPE_NULL)
+ fields = debug_get_fields (minfo->dhandle, context);
+
+ context = DEBUG_TYPE_NULL;
+
+ if (fields != NULL)
+ {
+ char *name;
+
+ /* Try to find the type by looking through the
+ fields of context until we find a field with the
+ same type. This ought to work for a class
+ defined within a class, but it won't work for,
+ e.g., an enum defined within a class. stabs does
+ not give us enough information to figure out the
+ latter case. */
+
+ name = savestring (*pp, len);
+
+ for (; *fields != DEBUG_FIELD_NULL; fields++)
+ {
+ debug_type ft;
+ const char *dn;
+
+ ft = debug_get_field_type (minfo->dhandle, *fields);
+ if (ft == NULL)
+ return false;
+ dn = debug_get_type_name (minfo->dhandle, ft);
+ if (dn != NULL && strcmp (dn, name) == 0)
+ {
+ context = ft;
+ break;
+ }
+ }
+
+ free (name);
+ }
+
+ if (context == DEBUG_TYPE_NULL)
+ {
+ /* We have to fall back on finding the type by name.
+ If there are more types to come, then this must
+ be a class. Otherwise, it could be anything. */
+
+ if (qualifiers == 0)
+ {
+ char *name;
+
+ name = savestring (*pp, len);
+ context = debug_find_named_type (minfo->dhandle,
+ name);
+ free (name);
+ }
+
+ if (context == DEBUG_TYPE_NULL)
+ {
+ context = stab_find_tagged_type (minfo->dhandle,
+ minfo->info,
+ *pp, len,
+ (qualifiers == 0
+ ? DEBUG_KIND_ILLEGAL
+ : DEBUG_KIND_CLASS));
+ if (context == DEBUG_TYPE_NULL)
+ return false;
+ }
+ }
+ }
+
+ *pp += len;
+ }
+ }
+
+ if (ptype != NULL)
+ *ptype = context;
+
+ return true;
+}
+
+/* Demangle a template. */
+
+static boolean
+stab_demangle_template (minfo, pp)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+{
+ const char *orig;
+ unsigned int r, i;
+
+ orig = *pp;
+
+ ++*pp;
+
+ /* Skip the template name. */
+ r = stab_demangle_count (pp);
+ if (r == 0 || strlen (*pp) < r)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ *pp += r;
+
+ /* Get the size of the parameter list. */
+ if (stab_demangle_get_count (pp, &r) == 0)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ for (i = 0; i < r; i++)
+ {
+ if (**pp == 'Z')
+ {
+ /* This is a type parameter. */
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
+ return false;
+ }
+ else
+ {
+ const char *old_p;
+ boolean pointerp, realp, integralp, charp, boolp;
+ boolean done;
+
+ old_p = *pp;
+ pointerp = false;
+ realp = false;
+ integralp = false;
+ charp = false;
+ boolp = false;
+ done = false;
+
+ /* This is a value parameter. */
+
+ if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
+ return false;
+
+ while (*old_p != '\0' && ! done)
+ {
+ switch (*old_p)
+ {
+ case 'P':
+ case 'p':
+ case 'R':
+ pointerp = true;
+ done = true;
+ break;
+ case 'C': /* Const. */
+ case 'S': /* Signed. */
+ case 'U': /* Unsigned. */
+ case 'V': /* Volatile. */
+ case 'F': /* Function. */
+ case 'M': /* Member function. */
+ case 'O': /* ??? */
+ ++old_p;
+ break;
+ case 'Q': /* Qualified name. */
+ integralp = true;
+ done = true;
+ break;
+ case 'T': /* Remembered type. */
+ abort ();
+ case 'v': /* Void. */
+ abort ();
+ case 'x': /* Long long. */
+ case 'l': /* Long. */
+ case 'i': /* Int. */
+ case 's': /* Short. */
+ case 'w': /* Wchar_t. */
+ integralp = true;
+ done = true;
+ break;
+ case 'b': /* Bool. */
+ boolp = true;
+ done = true;
+ break;
+ case 'c': /* Char. */
+ charp = true;
+ done = true;
+ break;
+ case 'r': /* Long double. */
+ case 'd': /* Double. */
+ case 'f': /* Float. */
+ realp = true;
+ done = true;
+ break;
+ default:
+ /* Assume it's a uder defined integral type. */
+ integralp = true;
+ done = true;
+ break;
+ }
+ }
+
+ if (integralp)
+ {
+ if (**pp == 'm')
+ ++*pp;
+ while (isdigit ((unsigned char) **pp))
+ ++*pp;
+ }
+ else if (charp)
+ {
+ unsigned int val;
+
+ if (**pp == 'm')
+ ++*pp;
+ val = stab_demangle_count (pp);
+ if (val == 0)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ }
+ else if (boolp)
+ {
+ unsigned int val;
+
+ val = stab_demangle_count (pp);
+ if (val != 0 && val != 1)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ }
+ else if (realp)
+ {
+ if (**pp == 'm')
+ ++*pp;
+ while (isdigit ((unsigned char) **pp))
+ ++*pp;
+ if (**pp == '.')
+ {
+ ++*pp;
+ while (isdigit ((unsigned char) **pp))
+ ++*pp;
+ }
+ if (**pp == 'e')
+ {
+ ++*pp;
+ while (isdigit ((unsigned char) **pp))
+ ++*pp;
+ }
+ }
+ else if (pointerp)
+ {
+ unsigned int len;
+
+ if (! stab_demangle_get_count (pp, &len))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ *pp += len;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Demangle a class name. */
+
+static boolean
+stab_demangle_class (minfo, pp, pstart)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ const char **pstart;
+{
+ const char *orig;
+ unsigned int n;
+
+ orig = *pp;
+
+ n = stab_demangle_count (pp);
+ if (strlen (*pp) < n)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ if (pstart != NULL)
+ *pstart = *pp;
+
+ *pp += n;
+
+ return true;
+}
+
+/* Demangle function arguments. If the pargs argument is not NULL, it
+ is set to a NULL terminated array holding the arguments. */
+
+static boolean
+stab_demangle_args (minfo, pp, pargs, pvarargs)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ debug_type **pargs;
+ boolean *pvarargs;
+{
+ const char *orig;
+ unsigned int alloc, count;
+
+ orig = *pp;
+
+ alloc = 10;
+ if (pargs != NULL)
+ {
+ *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
+ *pvarargs = false;
+ }
+ count = 0;
+
+ while (**pp != '_' && **pp != '\0' && **pp != 'e')
+ {
+ if (**pp == 'N' || **pp == 'T')
+ {
+ char temptype;
+ unsigned int r, t;
+
+ temptype = **pp;
+ ++*pp;
+
+ if (temptype == 'T')
+ r = 1;
+ else
+ {
+ if (! stab_demangle_get_count (pp, &r))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ }
+
+ if (! stab_demangle_get_count (pp, &t))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ if (t >= minfo->typestring_count)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ while (r-- > 0)
+ {
+ const char *tem;
+
+ tem = minfo->typestrings[t].typestring;
+ if (! stab_demangle_arg (minfo, &tem, pargs, &count, &alloc))
+ return false;
+ }
+ }
+ else
+ {
+ if (! stab_demangle_arg (minfo, pp, pargs, &count, &alloc))
+ return false;
+ }
+ }
+
+ if (pargs != NULL)
+ (*pargs)[count] = DEBUG_TYPE_NULL;
+
+ if (**pp == 'e')
+ {
+ if (pargs != NULL)
+ *pvarargs = true;
+ ++*pp;
+ }
+
+ return true;
+}
+
+/* Demangle a single argument. */
+
+static boolean
+stab_demangle_arg (minfo, pp, pargs, pcount, palloc)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ debug_type **pargs;
+ unsigned int *pcount;
+ unsigned int *palloc;
+{
+ const char *start;
+ debug_type type;
+
+ start = *pp;
+ if (! stab_demangle_type (minfo, pp,
+ pargs == NULL ? (debug_type *) NULL : &type)
+ || ! stab_demangle_remember_type (minfo, start, *pp - start))
+ return false;
+
+ if (pargs != NULL)
+ {
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ if (*pcount + 1 >= *palloc)
+ {
+ *palloc += 10;
+ *pargs = ((debug_type *)
+ xrealloc (*pargs, *palloc * sizeof **pargs));
+ }
+ (*pargs)[*pcount] = type;
+ ++*pcount;
+ }
+
+ return true;
+}
+
+/* Demangle a type. If the ptype argument is not NULL, *ptype is set
+ to the newly allocated type. */
+
+static boolean
+stab_demangle_type (minfo, pp, ptype)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ debug_type *ptype;
+{
+ const char *orig;
+
+ orig = *pp;
+
+ switch (**pp)
+ {
+ case 'P':
+ case 'p':
+ /* A pointer type. */
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ *ptype = debug_make_pointer_type (minfo->dhandle, *ptype);
+ break;
+
+ case 'R':
+ /* A reference type. */
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ *ptype = debug_make_reference_type (minfo->dhandle, *ptype);
+ break;
+
+ case 'A':
+ /* An array. */
+ {
+ unsigned long high;
+
+ ++*pp;
+ high = 0;
+ while (**pp != '\0' && **pp != '_')
+ {
+ if (! isdigit ((unsigned char) **pp))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ high *= 10;
+ high += **pp - '0';
+ ++*pp;
+ }
+ if (**pp != '_')
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ ++*pp;
+
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ {
+ debug_type int_type;
+
+ int_type = debug_find_named_type (minfo->dhandle, "int");
+ if (int_type == NULL)
+ int_type = debug_make_int_type (minfo->dhandle, 4, false);
+ *ptype = debug_make_array_type (minfo->dhandle, *ptype, int_type,
+ 0, high, false);
+ }
+ }
+ break;
+
+ case 'T':
+ /* A back reference to a remembered type. */
+ {
+ unsigned int i;
+ const char *p;
+
+ ++*pp;
+ if (! stab_demangle_get_count (pp, &i))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ if (i >= minfo->typestring_count)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ p = minfo->typestrings[i].typestring;
+ if (! stab_demangle_type (minfo, &p, ptype))
+ return false;
+ }
+ break;
+
+ case 'F':
+ /* A function. */
+ {
+ debug_type *args;
+ boolean varargs;
+
+ ++*pp;
+ if (! stab_demangle_args (minfo, pp,
+ (ptype == NULL
+ ? (debug_type **) NULL
+ : &args),
+ (ptype == NULL
+ ? (boolean *) NULL
+ : &varargs)))
+ return false;
+ if (**pp != '_')
+ {
+ /* cplus_demangle will accept a function without a return
+ type, but I don't know when that will happen, or what
+ to do if it does. */
+ stab_bad_demangle (orig);
+ return false;
+ }
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ *ptype = debug_make_function_type (minfo->dhandle, *ptype, args,
+ varargs);
+
+ }
+ break;
+
+ case 'M':
+ case 'O':
+ {
+ boolean memberp, constp, volatilep;
+ debug_type *args;
+ boolean varargs;
+ unsigned int n;
+ const char *name;
+
+ memberp = **pp == 'M';
+ constp = false;
+ volatilep = false;
+ args = NULL;
+ varargs = false;
+
+ ++*pp;
+ if (! isdigit ((unsigned char) **pp))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ n = stab_demangle_count (pp);
+ if (strlen (*pp) < n)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ name = *pp;
+ *pp += n;
+
+ if (memberp)
+ {
+ if (**pp == 'C')
+ {
+ constp = true;
+ ++*pp;
+ }
+ else if (**pp == 'V')
+ {
+ volatilep = true;
+ ++*pp;
+ }
+ if (**pp != 'F')
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ ++*pp;
+ if (! stab_demangle_args (minfo, pp,
+ (ptype == NULL
+ ? (debug_type **) NULL
+ : &args),
+ (ptype == NULL
+ ? (boolean *) NULL
+ : &varargs)))
+ return false;
+ }
+
+ if (**pp != '_')
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ ++*pp;
+
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+
+ if (ptype != NULL)
+ {
+ debug_type class_type;
+
+ class_type = stab_find_tagged_type (minfo->dhandle, minfo->info,
+ name, (int) n,
+ DEBUG_KIND_CLASS);
+ if (class_type == DEBUG_TYPE_NULL)
+ return false;
+
+ if (! memberp)
+ *ptype = debug_make_offset_type (minfo->dhandle, class_type,
+ *ptype);
+ else
+ {
+ /* FIXME: We have no way to record constp or
+ volatilep. */
+ *ptype = debug_make_method_type (minfo->dhandle, *ptype,
+ class_type, args, varargs);
+ }
+ }
+ }
+ break;
+
+ case 'G':
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ break;
+
+ case 'C':
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ *ptype = debug_make_const_type (minfo->dhandle, *ptype);
+ break;
+
+ case 'Q':
+ {
+ const char *hold;
+
+ hold = *pp;
+ if (! stab_demangle_qualified (minfo, pp, ptype))
+ return false;
+ }
+ break;
+
+ default:
+ if (! stab_demangle_fund_type (minfo, pp, ptype))
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+/* Demangle a fundamental type. If the ptype argument is not NULL,
+ *ptype is set to the newly allocated type. */
+
+static boolean
+stab_demangle_fund_type (minfo, pp, ptype)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ debug_type *ptype;
+{
+ const char *orig;
+ boolean constp, volatilep, unsignedp, signedp;
+ boolean done;
+
+ orig = *pp;
+
+ constp = false;
+ volatilep = false;
+ unsignedp = false;
+ signedp = false;
+
+ done = false;
+ while (! done)
+ {
+ switch (**pp)
+ {
+ case 'C':
+ constp = true;
+ ++*pp;
+ break;
+
+ case 'U':
+ unsignedp = true;
+ ++*pp;
+ break;
+
+ case 'S':
+ signedp = true;
+ ++*pp;
+ break;
+
+ case 'V':
+ volatilep = true;
+ ++*pp;
+ break;
+
+ default:
+ done = true;
+ break;
+ }
+ }
+
+ switch (**pp)
+ {
+ case '\0':
+ case '_':
+ /* cplus_demangle permits this, but I don't know what it means. */
+ stab_bad_demangle (orig);
+ break;
+
+ case 'v': /* void */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "void");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_void_type (minfo->dhandle);
+ }
+ ++*pp;
+ break;
+
+ case 'x': /* long long */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle,
+ (unsignedp
+ ? "long long unsigned int"
+ : "long long int"));
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 8, unsignedp);
+ }
+ ++*pp;
+ break;
+
+ case 'l': /* long */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle,
+ (unsignedp
+ ? "long unsigned int"
+ : "long int"));
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
+ }
+ ++*pp;
+ break;
+
+ case 'i': /* int */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle,
+ (unsignedp
+ ? "unsigned int"
+ : "int"));
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
+ }
+ ++*pp;
+ break;
+
+ case 's': /* short */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle,
+ (unsignedp
+ ? "short unsigned int"
+ : "short int"));
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 2, unsignedp);
+ }
+ ++*pp;
+ break;
+
+ case 'b': /* bool */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "bool");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_bool_type (minfo->dhandle, 4);
+ }
+ ++*pp;
+ break;
+
+ case 'c': /* char */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle,
+ (unsignedp
+ ? "unsigned char"
+ : (signedp
+ ? "signed char"
+ : "char")));
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 1, unsignedp);
+ }
+ ++*pp;
+ break;
+
+ case 'w': /* wchar_t */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "__wchar_t");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 2, true);
+ }
+ ++*pp;
+ break;
+
+ case 'r': /* long double */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "long double");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_float_type (minfo->dhandle, 8);
+ }
+ ++*pp;
+ break;
+
+ case 'd': /* double */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "double");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_float_type (minfo->dhandle, 8);
+ }
+ ++*pp;
+ break;
+
+ case 'f': /* float */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "float");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_float_type (minfo->dhandle, 4);
+ }
+ ++*pp;
+ break;
+
+ case 'G':
+ ++*pp;
+ if (! isdigit ((unsigned char) **pp))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ /* Fall through. */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ const char *hold;
+
+ if (! stab_demangle_class (minfo, pp, &hold))
+ return false;
+ if (ptype != NULL)
+ {
+ char *name;
+
+ name = savestring (hold, *pp - hold);
+ *ptype = debug_find_named_type (minfo->dhandle, name);
+ if (*ptype == DEBUG_TYPE_NULL)
+ {
+ /* FIXME: It is probably incorrect to assume that
+ undefined types are tagged types. */
+ *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
+ hold, *pp - hold,
+ DEBUG_KIND_ILLEGAL);
+ }
+ free (name);
+ }
+ }
+ break;
+
+ case 't':
+ if (! stab_demangle_template (minfo, pp))
+ return false;
+ abort ();
+ break;
+
+ default:
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ if (ptype != NULL)
+ {
+ if (constp)
+ *ptype = debug_make_const_type (minfo->dhandle, *ptype);
+ if (volatilep)
+ *ptype = debug_make_volatile_type (minfo->dhandle, *ptype);
+ }
+
+ return true;
+}
+
+/* Remember a type string in a demangled string. */
+
+static boolean
+stab_demangle_remember_type (minfo, p, len)
+ struct stab_demangle_info *minfo;
+ const char *p;
+ int len;
+{
+ if (minfo->typestring_count >= minfo->typestring_alloc)
+ {
+ minfo->typestring_alloc += 10;
+ minfo->typestrings = ((struct stab_demangle_typestring *)
+ xrealloc (minfo->typestrings,
+ (minfo->typestring_alloc
+ * sizeof *minfo->typestrings)));
+ }
+
+ minfo->typestrings[minfo->typestring_count].typestring = p;
+ minfo->typestrings[minfo->typestring_count].len = (unsigned int) len;
+ ++minfo->typestring_count;
+
+ return true;
+}
diff --git a/gnu/usr.bin/binutils/binutils/wrstabs.c b/gnu/usr.bin/binutils/binutils/wrstabs.c
new file mode 100644
index 00000000000..a4a7293c6a3
--- /dev/null
+++ b/gnu/usr.bin/binutils/binutils/wrstabs.c
@@ -0,0 +1,2404 @@
+/* wrstabs.c -- Output stabs debugging information
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ 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. */
+
+/* This file contains code which writes out stabs debugging
+ information. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* Meaningless definition needs by aout64.h. FIXME. */
+#define BYTES_IN_WORD 4
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+
+/* The size of a stabs symbol. This presumes 32 bit values. */
+
+#define STAB_SYMBOL_SIZE (12)
+
+/* An entry in a string hash table. */
+
+struct string_hash_entry
+{
+ struct bfd_hash_entry root;
+ /* Index in string table. */
+ long index;
+ /* Size of type if this is a typedef. */
+ unsigned int size;
+};
+
+/* A string hash table. */
+
+struct string_hash_table
+{
+ struct bfd_hash_table table;
+};
+
+/* The type stack. Each element on the stack is a string. */
+
+struct stab_type_stack
+{
+ /* The next element on the stack. */
+ struct stab_type_stack *next;
+ /* This element as a string. */
+ char *string;
+ /* The type index of this element. */
+ long index;
+ /* The size of the type. */
+ unsigned int size;
+ /* Whether type string defines a new type. */
+ boolean definition;
+ /* String defining struct fields. */
+ char *fields;
+ /* NULL terminated array of strings defining base classes for a
+ class. */
+ char **baseclasses;
+ /* String defining class methods. */
+ char *methods;
+ /* String defining vtable pointer for a class. */
+ char *vtable;
+};
+
+/* This structure is used to keep track of type indices for tagged
+ types. */
+
+struct stab_tag
+{
+ /* The type index. */
+ long index;
+ /* The tag name. */
+ const char *tag;
+ /* The kind of type. This is set to DEBUG_KIND_ILLEGAL when the
+ type is defined. */
+ enum debug_type_kind kind;
+ /* The size of the struct. */
+ unsigned int size;
+};
+
+/* We remember various sorts of type indices. They are not related,
+ but, for convenience, we keep all the information in this
+ structure. */
+
+struct stab_type_cache
+{
+ /* The void type index. */
+ long void_type;
+ /* Signed integer type indices, indexed by size - 1. */
+ long signed_integer_types[8];
+ /* Unsigned integer type indices, indexed by size - 1. */
+ long unsigned_integer_types[8];
+ /* Floating point types, indexed by size - 1. */
+ long float_types[16];
+ /* Pointers to types, indexed by the type index. */
+ long *pointer_types;
+ size_t pointer_types_alloc;
+ /* Functions returning types, indexed by the type index. */
+ long *function_types;
+ size_t function_types_alloc;
+ /* References to types, indexed by the type index. */
+ long *reference_types;
+ size_t reference_types_alloc;
+ /* Struct/union/class type indices, indexed by the struct id. */
+ struct stab_tag *struct_types;
+ size_t struct_types_alloc;
+};
+
+/* This is the handle passed through debug_write. */
+
+struct stab_write_handle
+{
+ /* The BFD. */
+ bfd *abfd;
+ /* This buffer holds the symbols. */
+ bfd_byte *symbols;
+ size_t symbols_size;
+ size_t symbols_alloc;
+ /* This buffer holds the strings. */
+ bfd_byte *strings;
+ size_t strings_size;
+ size_t strings_alloc;
+ /* This hash table eliminates duplicate strings. */
+ struct string_hash_table strhash;
+ /* The type stack. */
+ struct stab_type_stack *type_stack;
+ /* The next type index. */
+ long type_index;
+ /* The type cache. */
+ struct stab_type_cache type_cache;
+ /* A mapping from typedef names to type indices. */
+ struct string_hash_table typedef_hash;
+ /* If this is not -1, it is the offset to the most recent N_SO
+ symbol, and the value of that symbol needs to be set. */
+ long so_offset;
+ /* If this is not -1, it is the offset to the most recent N_FUN
+ symbol, and the value of that symbol needs to be set. */
+ long fun_offset;
+ /* The last text section address seen. */
+ bfd_vma last_text_address;
+ /* The block nesting depth. */
+ unsigned int nesting;
+ /* The function address. */
+ bfd_vma fnaddr;
+ /* A pending LBRAC symbol. */
+ bfd_vma pending_lbrac;
+ /* The current line number file name. */
+ const char *lineno_filename;
+};
+
+static struct bfd_hash_entry *string_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static boolean stab_write_symbol
+ PARAMS ((struct stab_write_handle *, int, int, bfd_vma, const char *));
+static boolean stab_push_string
+ PARAMS ((struct stab_write_handle *, const char *, long, boolean,
+ unsigned int));
+static boolean stab_push_defined_type
+ PARAMS ((struct stab_write_handle *, long, unsigned int));
+static char *stab_pop_type PARAMS ((struct stab_write_handle *));
+static boolean stab_modify_type
+ PARAMS ((struct stab_write_handle *, int, unsigned int, long **, size_t *));
+static long stab_get_struct_index
+ PARAMS ((struct stab_write_handle *, const char *, unsigned int,
+ enum debug_type_kind, unsigned int *));
+static boolean stab_class_method_var
+ PARAMS ((struct stab_write_handle *, const char *, enum debug_visibility,
+ boolean, boolean, boolean, bfd_vma, boolean));
+
+static boolean stab_start_compilation_unit PARAMS ((PTR, const char *));
+static boolean stab_start_source PARAMS ((PTR, const char *));
+static boolean stab_empty_type PARAMS ((PTR));
+static boolean stab_void_type PARAMS ((PTR));
+static boolean stab_int_type PARAMS ((PTR, unsigned int, boolean));
+static boolean stab_float_type PARAMS ((PTR, unsigned int));
+static boolean stab_complex_type PARAMS ((PTR, unsigned int));
+static boolean stab_bool_type PARAMS ((PTR, unsigned int));
+static boolean stab_enum_type
+ PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
+static boolean stab_pointer_type PARAMS ((PTR));
+static boolean stab_function_type PARAMS ((PTR, int, boolean));
+static boolean stab_reference_type PARAMS ((PTR));
+static boolean stab_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+static boolean stab_array_type
+ PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean));
+static boolean stab_set_type PARAMS ((PTR, boolean));
+static boolean stab_offset_type PARAMS ((PTR));
+static boolean stab_method_type PARAMS ((PTR, boolean, int, boolean));
+static boolean stab_const_type PARAMS ((PTR));
+static boolean stab_volatile_type PARAMS ((PTR));
+static boolean stab_start_struct_type
+ PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
+static boolean stab_struct_field
+ PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static boolean stab_end_struct_type PARAMS ((PTR));
+static boolean stab_start_class_type
+ PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
+ boolean));
+static boolean stab_class_static_member
+ PARAMS ((PTR, const char *, const char *, enum debug_visibility));
+static boolean stab_class_baseclass
+ PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility));
+static boolean stab_class_start_method PARAMS ((PTR, const char *));
+static boolean stab_class_method_variant
+ PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean,
+ bfd_vma, boolean));
+static boolean stab_class_static_method_variant
+ PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean));
+static boolean stab_class_end_method PARAMS ((PTR));
+static boolean stab_end_class_type PARAMS ((PTR));
+static boolean stab_typedef_type PARAMS ((PTR, const char *));
+static boolean stab_tag_type
+ PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
+static boolean stab_typdef PARAMS ((PTR, const char *));
+static boolean stab_tag PARAMS ((PTR, const char *));
+static boolean stab_int_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean stab_float_constant PARAMS ((PTR, const char *, double));
+static boolean stab_typed_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean stab_variable
+ PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
+static boolean stab_start_function PARAMS ((PTR, const char *, boolean));
+static boolean stab_function_parameter
+ PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
+static boolean stab_start_block PARAMS ((PTR, bfd_vma));
+static boolean stab_end_block PARAMS ((PTR, bfd_vma));
+static boolean stab_end_function PARAMS ((PTR));
+static boolean stab_lineno
+ PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+
+static const struct debug_write_fns stab_fns =
+{
+ stab_start_compilation_unit,
+ stab_start_source,
+ stab_empty_type,
+ stab_void_type,
+ stab_int_type,
+ stab_float_type,
+ stab_complex_type,
+ stab_bool_type,
+ stab_enum_type,
+ stab_pointer_type,
+ stab_function_type,
+ stab_reference_type,
+ stab_range_type,
+ stab_array_type,
+ stab_set_type,
+ stab_offset_type,
+ stab_method_type,
+ stab_const_type,
+ stab_volatile_type,
+ stab_start_struct_type,
+ stab_struct_field,
+ stab_end_struct_type,
+ stab_start_class_type,
+ stab_class_static_member,
+ stab_class_baseclass,
+ stab_class_start_method,
+ stab_class_method_variant,
+ stab_class_static_method_variant,
+ stab_class_end_method,
+ stab_end_class_type,
+ stab_typedef_type,
+ stab_tag_type,
+ stab_typdef,
+ stab_tag,
+ stab_int_constant,
+ stab_float_constant,
+ stab_typed_constant,
+ stab_variable,
+ stab_start_function,
+ stab_function_parameter,
+ stab_start_block,
+ stab_end_block,
+ stab_end_function,
+ stab_lineno
+};
+
+/* Routine to create an entry in a string hash table. */
+
+static struct bfd_hash_entry *
+string_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct string_hash_entry *ret = (struct string_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct string_hash_entry *) NULL)
+ ret = ((struct string_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct string_hash_entry)));
+ if (ret == (struct string_hash_entry *) NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct string_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+
+ if (ret)
+ {
+ /* Initialize the local fields. */
+ ret->index = -1;
+ ret->size = 0;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Look up an entry in a string hash table. */
+
+#define string_hash_lookup(t, string, create, copy) \
+ ((struct string_hash_entry *) \
+ bfd_hash_lookup (&(t)->table, (string), (create), (copy)))
+
+/* Add a symbol to the stabs debugging information we are building. */
+
+static boolean
+stab_write_symbol (info, type, desc, value, string)
+ struct stab_write_handle *info;
+ int type;
+ int desc;
+ bfd_vma value;
+ const char *string;
+{
+ bfd_size_type strx;
+ bfd_byte sym[STAB_SYMBOL_SIZE];
+
+ if (string == NULL)
+ strx = 0;
+ else
+ {
+ struct string_hash_entry *h;
+
+ h = string_hash_lookup (&info->strhash, string, true, false);
+ if (h == NULL)
+ {
+ fprintf (stderr, "string_hash_lookup failed: %s\n",
+ bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+ if (h->index != -1)
+ strx = h->index;
+ else
+ {
+ size_t len;
+
+ strx = info->strings_size;
+ h->index = strx;
+
+ len = strlen (string);
+ while (info->strings_size + len + 1 > info->strings_alloc)
+ {
+ info->strings_alloc *= 2;
+ info->strings = (bfd_byte *) xrealloc (info->strings,
+ info->strings_alloc);
+ }
+ strcpy (info->strings + info->strings_size, string);
+ info->strings_size += len + 1;
+ }
+ }
+
+ /* This presumes 32 bit values. */
+ bfd_put_32 (info->abfd, strx, sym);
+ bfd_put_8 (info->abfd, type, sym + 4);
+ bfd_put_8 (info->abfd, 0, sym + 5);
+ bfd_put_16 (info->abfd, desc, sym + 6);
+ bfd_put_32 (info->abfd, value, sym + 8);
+
+ if (info->symbols_size + STAB_SYMBOL_SIZE > info->symbols_alloc)
+ {
+ info->symbols_alloc *= 2;
+ info->symbols = (bfd_byte *) xrealloc (info->symbols,
+ info->symbols_alloc);
+ }
+
+ memcpy (info->symbols + info->symbols_size, sym, STAB_SYMBOL_SIZE);
+
+ info->symbols_size += STAB_SYMBOL_SIZE;
+
+ return true;
+}
+
+/* Push a string on to the type stack. */
+
+static boolean
+stab_push_string (info, string, index, definition, size)
+ struct stab_write_handle *info;
+ const char *string;
+ long index;
+ boolean definition;
+ unsigned int size;
+{
+ struct stab_type_stack *s;
+
+ s = (struct stab_type_stack *) xmalloc (sizeof *s);
+ s->string = xstrdup (string);
+ s->index = index;
+ s->definition = definition;
+ s->size = size;
+
+ s->fields = NULL;
+ s->baseclasses = NULL;
+ s->methods = NULL;
+ s->vtable = NULL;
+
+ s->next = info->type_stack;
+ info->type_stack = s;
+
+ return true;
+}
+
+/* Push a type index which has already been defined. */
+
+static boolean
+stab_push_defined_type (info, index, size)
+ struct stab_write_handle *info;
+ long index;
+ unsigned int size;
+{
+ char buf[20];
+
+ sprintf (buf, "%ld", index);
+ return stab_push_string (info, buf, index, false, size);
+}
+
+/* Pop a type off the type stack. The caller is responsible for
+ freeing the string. */
+
+static char *
+stab_pop_type (info)
+ struct stab_write_handle *info;
+{
+ struct stab_type_stack *s;
+ char *ret;
+
+ s = info->type_stack;
+ assert (s != NULL);
+
+ info->type_stack = s->next;
+
+ ret = s->string;
+
+ free (s);
+
+ return ret;
+}
+
+/* The general routine to write out stabs in sections debugging
+ information. This accumulates the stabs symbols and the strings in
+ two obstacks. We can't easily write out the information as we go
+ along, because we need to know the section sizes before we can
+ write out the section contents. ABFD is the BFD and DHANDLE is the
+ handle for the debugging information. This sets *PSYMS to point to
+ the symbols, *PSYMSIZE the size of the symbols, *PSTRINGS to the
+ strings, and *PSTRINGSIZE to the size of the strings. */
+
+boolean
+write_stabs_in_sections_debugging_info (abfd, dhandle, psyms, psymsize,
+ pstrings, pstringsize)
+ bfd *abfd;
+ PTR dhandle;
+ bfd_byte **psyms;
+ bfd_size_type *psymsize;
+ bfd_byte **pstrings;
+ bfd_size_type *pstringsize;
+{
+ struct stab_write_handle info;
+
+ info.abfd = abfd;
+
+ info.symbols_size = 0;
+ info.symbols_alloc = 500;
+ info.symbols = (bfd_byte *) xmalloc (info.symbols_alloc);
+
+ info.strings_size = 1;
+ info.strings_alloc = 500;
+ info.strings = (bfd_byte *) xmalloc (info.strings_alloc);
+ info.strings[0] = '\0';
+
+ if (! bfd_hash_table_init (&info.strhash.table, string_hash_newfunc)
+ || ! bfd_hash_table_init (&info.typedef_hash.table, string_hash_newfunc))
+ {
+ fprintf (stderr, "bfd_hash_table_init_failed: %s\n",
+ bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+
+ info.type_stack = NULL;
+ info.type_index = 1;
+ memset (&info.type_cache, 0, sizeof info.type_cache);
+ info.so_offset = -1;
+ info.fun_offset = -1;
+ info.last_text_address = 0;
+ info.nesting = 0;
+ info.fnaddr = 0;
+ info.pending_lbrac = (bfd_vma) -1;
+
+ /* The initial symbol holds the string size. */
+ if (! stab_write_symbol (&info, 0, 0, 0, (const char *) NULL))
+ return false;
+
+ /* Output an initial N_SO symbol. */
+ info.so_offset = info.symbols_size;
+ if (! stab_write_symbol (&info, N_SO, 0, 0, bfd_get_filename (abfd)))
+ return false;
+
+ if (! debug_write (dhandle, &stab_fns, (PTR) &info))
+ return false;
+
+ assert (info.pending_lbrac == (bfd_vma) -1);
+
+ /* Output a trailing N_SO. */
+ if (! stab_write_symbol (&info, N_SO, 0, info.last_text_address,
+ (const char *) NULL))
+ return false;
+
+ /* Put the string size in the initial symbol. */
+ bfd_put_32 (abfd, info.strings_size, info.symbols + 8);
+
+ *psyms = info.symbols;
+ *psymsize = info.symbols_size;
+
+ *pstrings = info.strings;
+ *pstringsize = info.strings_size;
+
+ return true;
+}
+
+/* Start writing out information for a compilation unit. */
+
+static boolean
+stab_start_compilation_unit (p, filename)
+ PTR p;
+ const char *filename;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ /* We would normally output an N_SO symbol here. However, that
+ would force us to reset all of our type information. I think we
+ will be better off just outputting an N_SOL symbol, and not
+ worrying about splitting information between files. */
+
+ info->lineno_filename = filename;
+
+ return stab_write_symbol (info, N_SOL, 0, 0, filename);
+}
+
+/* Start writing out information for a particular source file. */
+
+static boolean
+stab_start_source (p, filename)
+ PTR p;
+ const char *filename;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ /* FIXME: The symbol's value is supposed to be the text section
+ address. However, we would have to fill it in later, and gdb
+ doesn't care, so we don't bother with it. */
+
+ info->lineno_filename = filename;
+
+ return stab_write_symbol (info, N_SOL, 0, 0, filename);
+}
+
+/* Push an empty type. This shouldn't normally happen. We just use a
+ void type. */
+
+static boolean
+stab_empty_type (p)
+ PTR p;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ /* We don't call stab_void_type if the type is not yet defined,
+ because that might screw up the typedef. */
+
+ if (info->type_cache.void_type != 0)
+ return stab_push_defined_type (info, info->type_cache.void_type, 0);
+ else
+ {
+ long index;
+ char buf[40];
+
+ index = info->type_index;
+ ++info->type_index;
+
+ sprintf (buf, "%ld=%ld", index, index);
+
+ return stab_push_string (info, buf, index, false, 0);
+ }
+}
+
+/* Push a void type. */
+
+static boolean
+stab_void_type (p)
+ PTR p;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ if (info->type_cache.void_type != 0)
+ return stab_push_defined_type (info, info->type_cache.void_type, 0);
+ else
+ {
+ long index;
+ char buf[40];
+
+ index = info->type_index;
+ ++info->type_index;
+
+ info->type_cache.void_type = index;
+
+ sprintf (buf, "%ld=%ld", index, index);
+
+ return stab_push_string (info, buf, index, true, 0);
+ }
+}
+
+/* Push an integer type. */
+
+static boolean
+stab_int_type (p, size, unsignedp)
+ PTR p;
+ unsigned int size;
+ boolean unsignedp;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ long *cache;
+
+ if (size <= 0 || (size > sizeof (long) && size != 8))
+ {
+ fprintf (stderr, "stab_int_type: bad size %u\n", size);
+ return false;
+ }
+
+ if (unsignedp)
+ cache = info->type_cache.signed_integer_types;
+ else
+ cache = info->type_cache.unsigned_integer_types;
+
+ if (cache[size - 1] != 0)
+ return stab_push_defined_type (info, cache[size - 1], size);
+ else
+ {
+ long index;
+ char buf[100];
+
+ index = info->type_index;
+ ++info->type_index;
+
+ cache[size - 1] = index;
+
+ sprintf (buf, "%ld=r%ld;", index, index);
+ if (unsignedp)
+ {
+ strcat (buf, "0;");
+ if (size < sizeof (long))
+ sprintf (buf + strlen (buf), "%ld;", ((long) 1 << (size * 8)) - 1);
+ else if (size == sizeof (long))
+ strcat (buf, "-1;");
+ else if (size == 8)
+ strcat (buf, "01777777777777777777777;");
+ else
+ abort ();
+ }
+ else
+ {
+ if (size <= sizeof (long))
+ sprintf (buf + strlen (buf), "%ld;%ld;",
+ (long) - ((unsigned long) 1 << (size * 8 - 1)),
+ (long) (((unsigned long) 1 << (size * 8 - 1)) - 1));
+ else if (size == 8)
+ strcat (buf, "01000000000000000000000;0777777777777777777777;");
+ else
+ abort ();
+ }
+
+ return stab_push_string (info, buf, index, true, size);
+ }
+}
+
+/* Push a floating point type. */
+
+static boolean
+stab_float_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ if (size > 0
+ && size - 1 < (sizeof info->type_cache.float_types
+ / sizeof info->type_cache.float_types[0])
+ && info->type_cache.float_types[size - 1] != 0)
+ return stab_push_defined_type (info,
+ info->type_cache.float_types[size - 1],
+ size);
+ else
+ {
+ long index;
+ char *int_type;
+ char buf[50];
+
+ /* Floats are defined as a subrange of int. */
+ if (! stab_int_type (info, 4, false))
+ return false;
+ int_type = stab_pop_type (info);
+
+ index = info->type_index;
+ ++info->type_index;
+
+ if (size > 0
+ && size - 1 < (sizeof info->type_cache.float_types
+ / sizeof info->type_cache.float_types[0]))
+ info->type_cache.float_types[size - 1] = index;
+
+ sprintf (buf, "%ld=r%s;%u;0;", index, int_type, size);
+
+ free (int_type);
+
+ return stab_push_string (info, buf, index, true, size);
+ }
+}
+
+/* Push a complex type. */
+
+static boolean
+stab_complex_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ char buf[50];
+ long index;
+
+ index = info->type_index;
+ ++info->type_index;
+
+ sprintf (buf, "%ld=r%ld;%u;0;", index, index, size);
+
+ return stab_push_string (info, buf, index, true, size * 2);
+}
+
+/* Push a boolean type. We use an XCOFF predefined type, since gdb
+ always recognizes them. */
+
+static boolean
+stab_bool_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ long index;
+
+ switch (size)
+ {
+ case 1:
+ index = -21;
+ break;
+
+ case 2:
+ index = -22;
+ break;
+
+ default:
+ case 4:
+ index = -16;
+ break;
+
+ case 8:
+ index = -33;
+ break;
+ }
+
+ return stab_push_defined_type (info, index, size);
+}
+
+/* Push an enum type. */
+
+static boolean
+stab_enum_type (p, tag, names, vals)
+ PTR p;
+ const char *tag;
+ const char **names;
+ bfd_signed_vma *vals;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ size_t len;
+ const char **pn;
+ char *buf;
+ long index = 0;
+ bfd_signed_vma *pv;
+
+ if (names == NULL)
+ {
+ assert (tag != NULL);
+
+ buf = (char *) xmalloc (10 + strlen (tag));
+ sprintf (buf, "xe%s:", tag);
+ /* FIXME: The size is just a guess. */
+ if (! stab_push_string (info, buf, 0, false, 4))
+ return false;
+ free (buf);
+ return true;
+ }
+
+ len = 10;
+ if (tag != NULL)
+ len += strlen (tag);
+ for (pn = names; *pn != NULL; pn++)
+ len += strlen (*pn) + 20;
+
+ buf = (char *) xmalloc (len);
+
+ if (tag == NULL)
+ strcpy (buf, "e");
+ else
+ {
+ index = info->type_index;
+ ++info->type_index;
+ sprintf (buf, "%s:T%ld=e", tag, index);
+ }
+
+ for (pn = names, pv = vals; *pn != NULL; pn++, pv++)
+ sprintf (buf + strlen (buf), "%s:%ld,", *pn, (long) *pv);
+ strcat (buf, ";");
+
+ if (tag == NULL)
+ {
+ /* FIXME: The size is just a guess. */
+ if (! stab_push_string (info, buf, 0, false, 4))
+ return false;
+ }
+ else
+ {
+ /* FIXME: The size is just a guess. */
+ if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)
+ || ! stab_push_defined_type (info, index, 4))
+ return false;
+ }
+
+ free (buf);
+
+ return true;
+}
+
+/* Push a modification of the top type on the stack. Cache the
+ results in CACHE and CACHE_ALLOC. */
+
+static boolean
+stab_modify_type (info, mod, size, cache, cache_alloc)
+ struct stab_write_handle *info;
+ int mod;
+ unsigned int size;
+ long **cache;
+ size_t *cache_alloc;
+{
+ long targindex;
+ long index;
+ char *s, *buf;
+
+ assert (info->type_stack != NULL);
+ targindex = info->type_stack->index;
+
+ if (targindex <= 0
+ || cache == NULL)
+ {
+ boolean definition;
+
+ /* Either the target type has no index, or we aren't caching
+ this modifier. Either way we have no way of recording the
+ new type, so we don't bother to define one. */
+ definition = info->type_stack->definition;
+ s = stab_pop_type (info);
+ buf = (char *) xmalloc (strlen (s) + 2);
+ sprintf (buf, "%c%s", mod, s);
+ free (s);
+ if (! stab_push_string (info, buf, 0, definition, size))
+ return false;
+ free (buf);
+ }
+ else
+ {
+ if (targindex >= *cache_alloc)
+ {
+ size_t alloc;
+
+ alloc = *cache_alloc;
+ if (alloc == 0)
+ alloc = 10;
+ while (targindex >= alloc)
+ alloc *= 2;
+ *cache = (long *) xrealloc (*cache, alloc * sizeof (long));
+ memset (*cache + *cache_alloc, 0,
+ (alloc - *cache_alloc) * sizeof (long));
+ *cache_alloc = alloc;
+ }
+
+ index = (*cache)[targindex];
+ if (index != 0)
+ {
+ /* If we have already defined a modification of this type,
+ then the entry on the type stack can not be a definition,
+ so we can safely discard it. */
+ assert (! info->type_stack->definition);
+ free (stab_pop_type (info));
+ if (! stab_push_defined_type (info, index, size))
+ return false;
+ }
+ else
+ {
+ index = info->type_index;
+ ++info->type_index;
+
+ s = stab_pop_type (info);
+ buf = (char *) xmalloc (strlen (s) + 20);
+ sprintf (buf, "%ld=%c%s", index, mod, s);
+ free (s);
+
+ (*cache)[targindex] = index;
+
+ if (! stab_push_string (info, buf, index, true, size))
+ return false;
+
+ free (buf);
+ }
+ }
+
+ return true;
+}
+
+/* Push a pointer type. */
+
+static boolean
+stab_pointer_type (p)
+ PTR p;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ /* FIXME: The size should depend upon the architecture. */
+ return stab_modify_type (info, '*', 4, &info->type_cache.pointer_types,
+ &info->type_cache.pointer_types_alloc);
+}
+
+/* Push a function type. */
+
+static boolean
+stab_function_type (p, argcount, varargs)
+ PTR p;
+ int argcount;
+ boolean varargs;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ int i;
+
+ /* We have no way to represent the argument types, so we just
+ discard them. However, if they define new types, we must output
+ them. We do this by producing empty typedefs. */
+ for (i = 0; i < argcount; i++)
+ {
+ if (! info->type_stack->definition)
+ free (stab_pop_type (info));
+ else
+ {
+ char *s, *buf;
+
+ s = stab_pop_type (info);
+
+ buf = (char *) xmalloc (strlen (s) + 3);
+ sprintf (buf, ":t%s", s);
+ free (s);
+
+ if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+ return false;
+
+ free (buf);
+ }
+ }
+
+ return stab_modify_type (info, 'f', 0, &info->type_cache.function_types,
+ &info->type_cache.function_types_alloc);
+}
+
+/* Push a reference type. */
+
+static boolean
+stab_reference_type (p)
+ PTR p;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ /* FIXME: The size should depend upon the architecture. */
+ return stab_modify_type (info, '&', 4, &info->type_cache.reference_types,
+ &info->type_cache.reference_types_alloc);
+}
+
+/* Push a range type. */
+
+static boolean
+stab_range_type (p, low, high)
+ PTR p;
+ bfd_signed_vma low;
+ bfd_signed_vma high;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ boolean definition;
+ unsigned int size;
+ char *s, *buf;
+
+ definition = info->type_stack->definition;
+ size = info->type_stack->size;
+
+ s = stab_pop_type (info);
+ buf = (char *) xmalloc (strlen (s) + 100);
+ sprintf (buf, "r%s;%ld;%ld;", s, (long) low, (long) high);
+ free (s);
+
+ if (! stab_push_string (info, buf, 0, definition, size))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Push an array type. */
+
+static boolean
+stab_array_type (p, low, high, stringp)
+ PTR p;
+ bfd_signed_vma low;
+ bfd_signed_vma high;
+ boolean stringp;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ boolean definition;
+ unsigned int element_size;
+ char *range, *element, *buf;
+ long index;
+ unsigned int size;
+
+ definition = info->type_stack->definition;
+ range = stab_pop_type (info);
+
+ definition = definition || info->type_stack->definition;
+ element_size = info->type_stack->size;
+ element = stab_pop_type (info);
+
+ buf = (char *) xmalloc (strlen (range) + strlen (element) + 100);
+
+ if (! stringp)
+ {
+ index = 0;
+ *buf = '\0';
+ }
+ else
+ {
+ /* We need to define a type in order to include the string
+ attribute. */
+ index = info->type_index;
+ ++info->type_index;
+ definition = true;
+ sprintf (buf, "%ld=@S;", index);
+ }
+
+ sprintf (buf + strlen (buf), "ar%s;%ld;%ld;%s", range, low, high, element);
+ free (range);
+ free (element);
+
+ if (high <= low)
+ size = 0;
+ else
+ size = element_size * ((high - low) + 1);
+ if (! stab_push_string (info, buf, index, definition, size))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Push a set type. */
+
+static boolean
+stab_set_type (p, bitstringp)
+ PTR p;
+ boolean bitstringp;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ boolean definition;
+ char *s, *buf;
+ long index;
+
+ definition = info->type_stack->definition;
+
+ s = stab_pop_type (info);
+ buf = (char *) xmalloc (strlen (s) + 30);
+
+ if (! bitstringp)
+ {
+ *buf = '\0';
+ index = 0;
+ }
+ else
+ {
+ /* We need to define a type in order to include the string
+ attribute. */
+ index = info->type_index;
+ ++info->type_index;
+ definition = true;
+ sprintf (buf, "%ld=@S;", index);
+ }
+
+ sprintf (buf + strlen (buf), "S%s", s);
+ free (s);
+
+ if (! stab_push_string (info, buf, index, definition, 0))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Push an offset type. */
+
+static boolean
+stab_offset_type (p)
+ PTR p;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ boolean definition;
+ char *target, *base, *buf;
+
+ definition = info->type_stack->definition;
+ target = stab_pop_type (info);
+
+ definition = definition || info->type_stack->definition;
+ base = stab_pop_type (info);
+
+ buf = (char *) xmalloc (strlen (target) + strlen (base) + 3);
+ sprintf (buf, "@%s,%s", base, target);
+ free (base);
+ free (target);
+
+ if (! stab_push_string (info, buf, 0, definition, 0))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Push a method type. */
+
+static boolean
+stab_method_type (p, domainp, argcount, varargs)
+ PTR p;
+ boolean domainp;
+ int argcount;
+ boolean varargs;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ boolean definition;
+ char *domain, *return_type, *buf;
+ char **args;
+ int i;
+ size_t len;
+
+ /* We don't bother with stub method types, because that would
+ require a mangler for C++ argument types. This will waste space
+ in the debugging output. */
+
+ /* We need a domain. I'm not sure DOMAINP can ever be false,
+ anyhow. */
+ if (! domainp)
+ {
+ if (! stab_empty_type (p))
+ return false;
+ }
+
+ definition = info->type_stack->definition;
+ domain = stab_pop_type (info);
+
+ /* A non-varargs function is indicated by making the last parameter
+ type be void. */
+
+ if (argcount < 0)
+ {
+ args = NULL;
+ argcount = 0;
+ }
+ else if (argcount == 0)
+ {
+ if (varargs)
+ args = NULL;
+ else
+ {
+ args = (char **) xmalloc (1 * sizeof (*args));
+ if (! stab_empty_type (p))
+ return false;
+ definition = definition || info->type_stack->definition;
+ args[0] = stab_pop_type (info);
+ argcount = 1;
+ }
+ }
+ else
+ {
+ args = (char **) xmalloc ((argcount + 1) * sizeof (*args));
+ for (i = argcount - 1; i >= 0; i--)
+ {
+ definition = definition || info->type_stack->definition;
+ args[i] = stab_pop_type (info);
+ }
+ if (! varargs)
+ {
+ if (! stab_empty_type (p))
+ return false;
+ definition = definition || info->type_stack->definition;
+ args[argcount] = stab_pop_type (info);
+ ++argcount;
+ }
+ }
+
+ definition = definition || info->type_stack->definition;
+ return_type = stab_pop_type (info);
+
+ len = strlen (domain) + strlen (return_type) + 10;
+ for (i = 0; i < argcount; i++)
+ len += strlen (args[i]);
+
+ buf = (char *) xmalloc (len);
+
+ sprintf (buf, "#%s,%s", domain, return_type);
+ free (domain);
+ free (return_type);
+ for (i = 0; i < argcount; i++)
+ {
+ strcat (buf, ",");
+ strcat (buf, args[i]);
+ free (args[i]);
+ }
+ strcat (buf, ";");
+
+ if (args != NULL)
+ free (args);
+
+ if (! stab_push_string (info, buf, 0, definition, 0))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Push a const version of a type. */
+
+static boolean
+stab_const_type (p)
+ PTR p;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ return stab_modify_type (info, 'k', info->type_stack->size,
+ (long **) NULL, (size_t *) NULL);
+}
+
+/* Push a volatile version of a type. */
+
+static boolean
+stab_volatile_type (p)
+ PTR p;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ return stab_modify_type (info, 'B', info->type_stack->size,
+ (long **) NULL, (size_t *) NULL);
+}
+
+/* Get the type index to use for a struct/union/class ID. This should
+ return -1 if it fails. */
+
+static long
+stab_get_struct_index (info, tag, id, kind, psize)
+ struct stab_write_handle *info;
+ const char *tag;
+ unsigned int id;
+ enum debug_type_kind kind;
+ unsigned int *psize;
+{
+ if (id >= info->type_cache.struct_types_alloc)
+ {
+ size_t alloc;
+
+ alloc = info->type_cache.struct_types_alloc;
+ if (alloc == 0)
+ alloc = 10;
+ while (id >= alloc)
+ alloc *= 2;
+ info->type_cache.struct_types =
+ (struct stab_tag *) xrealloc (info->type_cache.struct_types,
+ alloc * sizeof (struct stab_tag));
+ memset ((info->type_cache.struct_types
+ + info->type_cache.struct_types_alloc),
+ 0,
+ ((alloc - info->type_cache.struct_types_alloc)
+ * sizeof (struct stab_tag)));
+ info->type_cache.struct_types_alloc = alloc;
+ }
+
+ if (info->type_cache.struct_types[id].index == 0)
+ {
+ info->type_cache.struct_types[id].index = info->type_index;
+ ++info->type_index;
+ info->type_cache.struct_types[id].tag = tag;
+ info->type_cache.struct_types[id].kind = kind;
+ }
+
+ if (kind == DEBUG_KIND_ILLEGAL)
+ {
+ /* This is a definition of the struct. */
+ info->type_cache.struct_types[id].kind = kind;
+ info->type_cache.struct_types[id].size = *psize;
+ }
+ else
+ *psize = info->type_cache.struct_types[id].size;
+
+ return info->type_cache.struct_types[id].index;
+}
+
+/* Start outputting a struct. We ignore the tag, and handle it in
+ stab_tag. */
+
+/*ARGSUSED*/
+static boolean
+stab_start_struct_type (p, tag, id, structp, size)
+ PTR p;
+ const char *tag;
+ unsigned int id;
+ boolean structp;
+ unsigned int size;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ long index;
+ boolean definition;
+ char *buf;
+
+ buf = (char *) xmalloc (40);
+
+ if (id == 0)
+ {
+ index = 0;
+ *buf = '\0';
+ definition = false;
+ }
+ else
+ {
+ index = stab_get_struct_index (info, tag, id, DEBUG_KIND_ILLEGAL,
+ &size);
+ if (index < 0)
+ return false;
+ sprintf (buf, "%ld=", index);
+ definition = true;
+ }
+
+ sprintf (buf + strlen (buf), "%c%u",
+ structp ? 's' : 'u',
+ size);
+
+ if (! stab_push_string (info, buf, index, definition, size))
+ return false;
+
+ info->type_stack->fields = (char *) xmalloc (1);
+ info->type_stack->fields[0] = '\0';
+
+ return true;
+}
+
+/* Add a field to a struct. */
+
+static boolean
+stab_struct_field (p, name, bitpos, bitsize, visibility)
+ PTR p;
+ const char *name;
+ bfd_vma bitpos;
+ bfd_vma bitsize;
+ enum debug_visibility visibility;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ boolean definition;
+ unsigned int size;
+ char *s, *n;
+ const char *vis;
+
+ definition = info->type_stack->definition;
+ size = info->type_stack->size;
+ s = stab_pop_type (info);
+
+ /* Add this field to the end of the current struct fields, which is
+ currently on the top of the stack. */
+
+ assert (info->type_stack->fields != NULL);
+ n = (char *) xmalloc (strlen (info->type_stack->fields)
+ + strlen (name)
+ + strlen (s)
+ + 50);
+
+ switch (visibility)
+ {
+ default:
+ abort ();
+
+ case DEBUG_VISIBILITY_PUBLIC:
+ vis = "";
+ break;
+
+ case DEBUG_VISIBILITY_PRIVATE:
+ vis = "/0";
+ break;
+
+ case DEBUG_VISIBILITY_PROTECTED:
+ vis = "/1";
+ break;
+ }
+
+ if (bitsize == 0)
+ {
+ bitsize = size * 8;
+ if (bitsize == 0)
+ fprintf (stderr,
+ "%s: warning: unknown size for field `%s' in struct\n",
+ bfd_get_filename (info->abfd), name);
+ }
+
+ sprintf (n, "%s%s:%s%s,%ld,%ld;", info->type_stack->fields, name, vis, s,
+ (long) bitpos, (long) bitsize);
+
+ free (info->type_stack->fields);
+ info->type_stack->fields = n;
+
+ if (definition)
+ info->type_stack->definition = true;
+
+ return true;
+}
+
+/* Finish up a struct. */
+
+static boolean
+stab_end_struct_type (p)
+ PTR p;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ boolean definition;
+ long index;
+ unsigned int size;
+ char *fields, *first, *buf;
+
+ assert (info->type_stack != NULL && info->type_stack->fields != NULL);
+
+ definition = info->type_stack->definition;
+ index = info->type_stack->index;
+ size = info->type_stack->size;
+ fields = info->type_stack->fields;
+ first = stab_pop_type (info);
+
+ buf = (char *) xmalloc (strlen (first) + strlen (fields) + 2);
+ sprintf (buf, "%s%s;", first, fields);
+ free (first);
+ free (fields);
+
+ if (! stab_push_string (info, buf, index, definition, size))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Start outputting a class. */
+
+static boolean
+stab_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
+ PTR p;
+ const char *tag;
+ unsigned int id;
+ boolean structp;
+ unsigned int size;
+ boolean vptr;
+ boolean ownvptr;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ boolean definition;
+ char *vstring;
+
+ if (! vptr || ownvptr)
+ {
+ definition = false;
+ vstring = NULL;
+ }
+ else
+ {
+ definition = info->type_stack->definition;
+ vstring = stab_pop_type (info);
+ }
+
+ if (! stab_start_struct_type (p, tag, id, structp, size))
+ return false;
+
+ if (vptr)
+ {
+ char *vtable;
+
+ if (ownvptr)
+ {
+ assert (info->type_stack->index > 0);
+ vtable = (char *) xmalloc (20);
+ sprintf (vtable, "~%%%ld", info->type_stack->index);
+ }
+ else
+ {
+ vtable = (char *) xmalloc (strlen (vstring) + 3);
+ sprintf (vtable, "~%%%s", vstring);
+ free (vstring);
+ }
+
+ info->type_stack->vtable = vtable;
+ }
+
+ if (definition)
+ info->type_stack->definition = true;
+
+ return true;
+}
+
+/* Add a static member to the class on the type stack. */
+
+static boolean
+stab_class_static_member (p, name, physname, visibility)
+ PTR p;
+ const char *name;
+ const char *physname;
+ enum debug_visibility visibility;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ boolean definition;
+ char *s, *n;
+ const char *vis;
+
+ definition = info->type_stack->definition;
+ s = stab_pop_type (info);
+
+ /* Add this field to the end of the current struct fields, which is
+ currently on the top of the stack. */
+
+ assert (info->type_stack->fields != NULL);
+ n = (char *) xmalloc (strlen (info->type_stack->fields)
+ + strlen (name)
+ + strlen (s)
+ + strlen (physname)
+ + 10);
+
+ switch (visibility)
+ {
+ default:
+ abort ();
+
+ case DEBUG_VISIBILITY_PUBLIC:
+ vis = "";
+ break;
+
+ case DEBUG_VISIBILITY_PRIVATE:
+ vis = "/0";
+ break;
+
+ case DEBUG_VISIBILITY_PROTECTED:
+ vis = "/1";
+ break;
+ }
+
+ sprintf (n, "%s%s:%s%s:%s;", info->type_stack->fields, name, vis, s,
+ physname);
+
+ free (info->type_stack->fields);
+ info->type_stack->fields = n;
+
+ if (definition)
+ info->type_stack->definition = true;
+
+ return true;
+}
+
+/* Add a base class to the class on the type stack. */
+
+static boolean
+stab_class_baseclass (p, bitpos, virtual, visibility)
+ PTR p;
+ bfd_vma bitpos;
+ boolean virtual;
+ enum debug_visibility visibility;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ boolean definition;
+ char *s;
+ char *buf;
+ unsigned int c;
+ char **baseclasses;
+
+ definition = info->type_stack->definition;
+ s = stab_pop_type (info);
+
+ /* Build the base class specifier. */
+
+ buf = (char *) xmalloc (strlen (s) + 25);
+ buf[0] = virtual ? '1' : '0';
+ switch (visibility)
+ {
+ default:
+ abort ();
+
+ case DEBUG_VISIBILITY_PRIVATE:
+ buf[1] = '0';
+ break;
+
+ case DEBUG_VISIBILITY_PROTECTED:
+ buf[1] = '1';
+ break;
+
+ case DEBUG_VISIBILITY_PUBLIC:
+ buf[1] = '2';
+ break;
+ }
+
+ sprintf (buf + 2, "%ld,%s;", (long) bitpos, s);
+ free (s);
+
+ /* Add the new baseclass to the existing ones. */
+
+ assert (info->type_stack != NULL && info->type_stack->fields != NULL);
+
+ if (info->type_stack->baseclasses == NULL)
+ c = 0;
+ else
+ {
+ c = 0;
+ while (info->type_stack->baseclasses[c] != NULL)
+ ++c;
+ }
+
+ baseclasses = (char **) xrealloc (info->type_stack->baseclasses,
+ (c + 2) * sizeof (*baseclasses));
+ baseclasses[c] = buf;
+ baseclasses[c + 1] = NULL;
+
+ info->type_stack->baseclasses = baseclasses;
+
+ if (definition)
+ info->type_stack->definition = true;
+
+ return true;
+}
+
+/* Start adding a method to the class on the type stack. */
+
+static boolean
+stab_class_start_method (p, name)
+ PTR p;
+ const char *name;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ char *m;
+
+ assert (info->type_stack != NULL && info->type_stack->fields != NULL);
+
+ if (info->type_stack->methods == NULL)
+ {
+ m = (char *) xmalloc (strlen (name) + 3);
+ *m = '\0';
+ }
+ else
+ {
+ m = (char *) xrealloc (info->type_stack->methods,
+ (strlen (info->type_stack->methods)
+ + strlen (name)
+ + 4));
+ }
+
+ sprintf (m + strlen (m), "%s::", name);
+
+ info->type_stack->methods = m;
+
+ return true;
+}
+
+/* Add a variant, either static or not, to the current method. */
+
+static boolean
+stab_class_method_var (info, physname, visibility, staticp, constp, volatilep,
+ voffset, contextp)
+ struct stab_write_handle *info;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean staticp;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ boolean contextp;
+{
+ boolean definition;
+ char *type;
+ char *context = NULL;
+ char visc, qualc, typec;
+
+ definition = info->type_stack->definition;
+ type = stab_pop_type (info);
+
+ if (contextp)
+ {
+ definition = definition || info->type_stack->definition;
+ context = stab_pop_type (info);
+ }
+
+ assert (info->type_stack != NULL && info->type_stack->methods != NULL);
+
+ switch (visibility)
+ {
+ default:
+ abort ();
+
+ case DEBUG_VISIBILITY_PRIVATE:
+ visc = '0';
+ break;
+
+ case DEBUG_VISIBILITY_PROTECTED:
+ visc = '1';
+ break;
+
+ case DEBUG_VISIBILITY_PUBLIC:
+ visc = '2';
+ break;
+ }
+
+ if (constp)
+ {
+ if (volatilep)
+ qualc = 'D';
+ else
+ qualc = 'B';
+ }
+ else
+ {
+ if (volatilep)
+ qualc = 'C';
+ else
+ qualc = 'A';
+ }
+
+ if (staticp)
+ typec = '?';
+ else if (! contextp)
+ typec = '.';
+ else
+ typec = '*';
+
+ info->type_stack->methods =
+ (char *) xrealloc (info->type_stack->methods,
+ (strlen (info->type_stack->methods)
+ + strlen (type)
+ + strlen (physname)
+ + (contextp ? strlen (context) : 0)
+ + 40));
+
+ sprintf (info->type_stack->methods + strlen (info->type_stack->methods),
+ "%s:%s;%c%c%c", type, physname, visc, qualc, typec);
+ free (type);
+
+ if (contextp)
+ {
+ sprintf (info->type_stack->methods + strlen (info->type_stack->methods),
+ "%ld;%s;", (long) voffset, context);
+ free (context);
+ }
+
+ if (definition)
+ info->type_stack->definition = true;
+
+ return true;
+}
+
+/* Add a variant to the current method. */
+
+static boolean
+stab_class_method_variant (p, physname, visibility, constp, volatilep,
+ voffset, contextp)
+ PTR p;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ boolean contextp;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ return stab_class_method_var (info, physname, visibility, false, constp,
+ volatilep, voffset, contextp);
+}
+
+/* Add a static variant to the current method. */
+
+static boolean
+stab_class_static_method_variant (p, physname, visibility, constp, volatilep)
+ PTR p;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ return stab_class_method_var (info, physname, visibility, true, constp,
+ volatilep, 0, false);
+}
+
+/* Finish up a method. */
+
+static boolean
+stab_class_end_method (p)
+ PTR p;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ assert (info->type_stack != NULL && info->type_stack->methods != NULL);
+
+ /* We allocated enough room on info->type_stack->methods to add the
+ trailing semicolon. */
+ strcat (info->type_stack->methods, ";");
+
+ return true;
+}
+
+/* Finish up a class. */
+
+static boolean
+stab_end_class_type (p)
+ PTR p;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ size_t len;
+ unsigned int i;
+ char *buf;
+
+ assert (info->type_stack != NULL && info->type_stack->fields != NULL);
+
+ /* Work out the size we need to allocate for the class definition. */
+
+ len = (strlen (info->type_stack->string)
+ + strlen (info->type_stack->fields)
+ + 10);
+ if (info->type_stack->baseclasses != NULL)
+ {
+ len += 20;
+ for (i = 0; info->type_stack->baseclasses[i] != NULL; i++)
+ len += strlen (info->type_stack->baseclasses[i]);
+ }
+ if (info->type_stack->methods != NULL)
+ len += strlen (info->type_stack->methods);
+ if (info->type_stack->vtable != NULL)
+ len += strlen (info->type_stack->vtable);
+
+ /* Build the class definition. */
+
+ buf = (char *) xmalloc (len);
+
+ strcpy (buf, info->type_stack->string);
+
+ if (info->type_stack->baseclasses != NULL)
+ {
+ sprintf (buf + strlen (buf), "!%u,", i);
+ for (i = 0; info->type_stack->baseclasses[i] != NULL; i++)
+ {
+ strcat (buf, info->type_stack->baseclasses[i]);
+ free (info->type_stack->baseclasses[i]);
+ }
+ free (info->type_stack->baseclasses);
+ info->type_stack->baseclasses = NULL;
+ }
+
+ strcat (buf, info->type_stack->fields);
+ free (info->type_stack->fields);
+ info->type_stack->fields = NULL;
+
+ if (info->type_stack->methods != NULL)
+ {
+ strcat (buf, info->type_stack->methods);
+ free (info->type_stack->methods);
+ info->type_stack->methods = NULL;
+ }
+
+ strcat (buf, ";");
+
+ if (info->type_stack->vtable != NULL)
+ {
+ strcat (buf, info->type_stack->vtable);
+ free (info->type_stack->vtable);
+ info->type_stack->vtable = NULL;
+ }
+
+ /* Replace the string on the top of the stack with the complete
+ class definition. */
+ free (info->type_stack->string);
+ info->type_stack->string = buf;
+
+ return true;
+}
+
+/* Push a typedef which was previously defined. */
+
+static boolean
+stab_typedef_type (p, name)
+ PTR p;
+ const char *name;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ struct string_hash_entry *h;
+
+ h = string_hash_lookup (&info->typedef_hash, name, false, false);
+ assert (h != NULL && h->index > 0);
+
+ return stab_push_defined_type (info, h->index, h->size);
+}
+
+/* Push a struct, union or class tag. */
+
+static boolean
+stab_tag_type (p, name, id, kind)
+ PTR p;
+ const char *name;
+ unsigned int id;
+ enum debug_type_kind kind;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ long index;
+ unsigned int size;
+
+ index = stab_get_struct_index (info, name, id, kind, &size);
+ if (index < 0)
+ return false;
+
+ return stab_push_defined_type (info, index, size);
+}
+
+/* Define a typedef. */
+
+static boolean
+stab_typdef (p, name)
+ PTR p;
+ const char *name;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ long index;
+ unsigned int size;
+ char *s, *buf;
+ struct string_hash_entry *h;
+
+ index = info->type_stack->index;
+ size = info->type_stack->size;
+ s = stab_pop_type (info);
+
+ buf = (char *) xmalloc (strlen (name) + strlen (s) + 20);
+
+ if (index > 0)
+ sprintf (buf, "%s:t%s", name, s);
+ else
+ {
+ index = info->type_index;
+ ++info->type_index;
+ sprintf (buf, "%s:t%ld=%s", name, index, s);
+ }
+
+ free (s);
+
+ if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+ return false;
+
+ free (buf);
+
+ h = string_hash_lookup (&info->typedef_hash, name, true, false);
+ if (h == NULL)
+ {
+ fprintf (stderr, "string_hash_lookup failed: %s\n",
+ bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+
+ /* I don't think we care about redefinitions. */
+
+ h->index = index;
+ h->size = size;
+
+ return true;
+}
+
+/* Define a tag. */
+
+static boolean
+stab_tag (p, tag)
+ PTR p;
+ const char *tag;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ char *s, *buf;
+
+ s = stab_pop_type (info);
+
+ buf = (char *) xmalloc (strlen (tag) + strlen (s) + 3);
+
+ sprintf (buf, "%s:T%s", tag, s);
+ free (s);
+
+ if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Define an integer constant. */
+
+static boolean
+stab_int_constant (p, name, val)
+ PTR p;
+ const char *name;
+ bfd_vma val;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ char *buf;
+
+ buf = (char *) xmalloc (strlen (name) + 20);
+ sprintf (buf, "%s:c=i%ld", name, (long) val);
+
+ if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Define a floating point constant. */
+
+static boolean
+stab_float_constant (p, name, val)
+ PTR p;
+ const char *name;
+ double val;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ char *buf;
+
+ buf = (char *) xmalloc (strlen (name) + 20);
+ sprintf (buf, "%s:c=f%g", name, val);
+
+ if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Define a typed constant. */
+
+static boolean
+stab_typed_constant (p, name, val)
+ PTR p;
+ const char *name;
+ bfd_vma val;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ char *s, *buf;
+
+ s = stab_pop_type (info);
+
+ buf = (char *) xmalloc (strlen (name) + strlen (s) + 20);
+ sprintf (buf, "%s:c=e%s,%ld", name, s, (long) val);
+ free (s);
+
+ if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Record a variable. */
+
+static boolean
+stab_variable (p, name, kind, val)
+ PTR p;
+ const char *name;
+ enum debug_var_kind kind;
+ bfd_vma val;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ char *s, *buf;
+ int stab_type;
+ const char *kindstr;
+
+ s = stab_pop_type (info);
+
+ switch (kind)
+ {
+ default:
+ abort ();
+
+ case DEBUG_GLOBAL:
+ stab_type = N_GSYM;
+ kindstr = "G";
+ break;
+
+ case DEBUG_STATIC:
+ stab_type = N_STSYM;
+ kindstr = "S";
+ break;
+
+ case DEBUG_LOCAL_STATIC:
+ stab_type = N_STSYM;
+ kindstr = "V";
+ break;
+
+ case DEBUG_LOCAL:
+ stab_type = N_LSYM;
+ kindstr = "";
+
+ /* Make sure that this is a type reference or definition. */
+ if (! isdigit (*s))
+ {
+ char *n;
+ long index;
+
+ index = info->type_index;
+ ++info->type_index;
+ n = (char *) xmalloc (strlen (s) + 20);
+ sprintf (n, "%ld=%s", index, s);
+ free (s);
+ s = n;
+ }
+ break;
+
+ case DEBUG_REGISTER:
+ stab_type = N_RSYM;
+ kindstr = "r";
+ break;
+ }
+
+ buf = (char *) xmalloc (strlen (name) + strlen (s) + 3);
+ sprintf (buf, "%s:%s%s", name, kindstr, s);
+ free (s);
+
+ if (! stab_write_symbol (info, stab_type, 0, val, buf))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Start outputting a function. */
+
+static boolean
+stab_start_function (p, name, globalp)
+ PTR p;
+ const char *name;
+ boolean globalp;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ char *rettype, *buf;
+
+ assert (info->nesting == 0 && info->fun_offset == -1);
+
+ rettype = stab_pop_type (info);
+
+ buf = (char *) xmalloc (strlen (name) + strlen (rettype) + 3);
+ sprintf (buf, "%s:%c%s", name,
+ globalp ? 'F' : 'f',
+ rettype);
+
+ /* We don't know the value now, so we set it in start_block. */
+ info->fun_offset = info->symbols_size;
+
+ if (! stab_write_symbol (info, N_FUN, 0, 0, buf))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Output a function parameter. */
+
+static boolean
+stab_function_parameter (p, name, kind, val)
+ PTR p;
+ const char *name;
+ enum debug_parm_kind kind;
+ bfd_vma val;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+ char *s, *buf;
+ int stab_type;
+ char kindc;
+
+ s = stab_pop_type (info);
+
+ switch (kind)
+ {
+ default:
+ abort ();
+
+ case DEBUG_PARM_STACK:
+ stab_type = N_PSYM;
+ kindc = 'p';
+ break;
+
+ case DEBUG_PARM_REG:
+ stab_type = N_RSYM;
+ kindc = 'P';
+ break;
+
+ case DEBUG_PARM_REFERENCE:
+ stab_type = N_PSYM;
+ kindc = 'v';
+ break;
+
+ case DEBUG_PARM_REF_REG:
+ stab_type = N_RSYM;
+ kindc = 'a';
+ break;
+ }
+
+ buf = (char *) xmalloc (strlen (name) + strlen (s) + 3);
+ sprintf (buf, "%s:%c%s", name, kindc, s);
+ free (s);
+
+ if (! stab_write_symbol (info, stab_type, 0, val, buf))
+ return false;
+
+ free (buf);
+
+ return true;
+}
+
+/* Start a block. */
+
+static boolean
+stab_start_block (p, addr)
+ PTR p;
+ bfd_vma addr;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ /* Fill in any slots which have been waiting for the first known
+ text address. */
+
+ if (info->so_offset != -1)
+ {
+ bfd_put_32 (info->abfd, addr, info->symbols + info->so_offset + 8);
+ info->so_offset = -1;
+ }
+
+ if (info->fun_offset != -1)
+ {
+ bfd_put_32 (info->abfd, addr, info->symbols + info->fun_offset + 8);
+ info->fun_offset = -1;
+ }
+
+ ++info->nesting;
+
+ /* We will be called with a top level block surrounding the
+ function, but stabs information does not output that block, so we
+ ignore it. */
+
+ if (info->nesting == 1)
+ {
+ info->fnaddr = addr;
+ return true;
+ }
+
+ /* We have to output the LBRAC symbol after any variables which are
+ declared inside the block. We postpone the LBRAC until the next
+ start_block or end_block. */
+
+ /* If we have postponed an LBRAC, output it now. */
+ if (info->pending_lbrac != (bfd_vma) -1)
+ {
+ if (! stab_write_symbol (info, N_LBRAC, 0, info->pending_lbrac,
+ (const char *) NULL))
+ return false;
+ }
+
+ /* Remember the address and output it later. */
+
+ info->pending_lbrac = addr - info->fnaddr;
+
+ return true;
+}
+
+/* End a block. */
+
+static boolean
+stab_end_block (p, addr)
+ PTR p;
+ bfd_vma addr;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ if (addr > info->last_text_address)
+ info->last_text_address = addr;
+
+ /* If we have postponed an LBRAC, output it now. */
+ if (info->pending_lbrac != (bfd_vma) -1)
+ {
+ if (! stab_write_symbol (info, N_LBRAC, 0, info->pending_lbrac,
+ (const char *) NULL))
+ return false;
+ info->pending_lbrac = (bfd_vma) -1;
+ }
+
+ assert (info->nesting > 0);
+
+ --info->nesting;
+
+ /* We ignore the outermost block. */
+ if (info->nesting == 0)
+ return true;
+
+ return stab_write_symbol (info, N_RBRAC, 0, addr - info->fnaddr,
+ (const char *) NULL);
+}
+
+/* End a function. */
+
+/*ARGSUSED*/
+static boolean
+stab_end_function (p)
+ PTR p;
+{
+ return true;
+}
+
+/* Output a line number. */
+
+static boolean
+stab_lineno (p, file, lineno, addr)
+ PTR p;
+ const char *file;
+ unsigned long lineno;
+ bfd_vma addr;
+{
+ struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+ assert (info->lineno_filename != NULL);
+
+ if (addr > info->last_text_address)
+ info->last_text_address = addr;
+
+ if (strcmp (file, info->lineno_filename) != 0)
+ {
+ if (! stab_write_symbol (info, N_SOL, 0, addr, file))
+ return false;
+ info->lineno_filename = file;
+ }
+
+ return stab_write_symbol (info, N_SLINE, lineno, addr - info->fnaddr,
+ (const char *) NULL);
+}
diff --git a/gnu/usr.bin/binutils/config/mh-m68kpic b/gnu/usr.bin/binutils/config/mh-m68kpic
new file mode 100644
index 00000000000..92e48d90fbd
--- /dev/null
+++ b/gnu/usr.bin/binutils/config/mh-m68kpic
@@ -0,0 +1 @@
+PICFLAG=-fpic
diff --git a/gnu/usr.bin/binutils/config/mh-necv4 b/gnu/usr.bin/binutils/config/mh-necv4
new file mode 100644
index 00000000000..e887736f8be
--- /dev/null
+++ b/gnu/usr.bin/binutils/config/mh-necv4
@@ -0,0 +1,11 @@
+# Host Makefile fragment for NEC MIPS SVR4.
+
+# The C compiler on NEC MIPS SVR4 needs bigger tables.
+CC = cc -ZXNd=5000 -ZXNg=1000
+
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV -DSVR4
+RANLIB = true
+
+# NEC -lX11 needs some other libraries.
+X11_EXTRA_LIBS = -lsocket -lnsl
diff --git a/gnu/usr.bin/binutils/config/mt-m68kpic b/gnu/usr.bin/binutils/config/mt-m68kpic
new file mode 100644
index 00000000000..ff987275575
--- /dev/null
+++ b/gnu/usr.bin/binutils/config/mt-m68kpic
@@ -0,0 +1 @@
+PICFLAG_FOR_TARGET=-fpic
diff --git a/gnu/usr.bin/binutils/etc/ChangeLog b/gnu/usr.bin/binutils/etc/ChangeLog
new file mode 100644
index 00000000000..7cf82e39c12
--- /dev/null
+++ b/gnu/usr.bin/binutils/etc/ChangeLog
@@ -0,0 +1,288 @@
+Fri Mar 29 11:38:01 1996 J.T. Conklin (jtc@lisa.cygnus.com)
+
+ * configure.man: Changed to be recognized by catman -w on Solaris.
+
+Wed Dec 6 15:40:28 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * comp-tools-fix (fixincludes): Define FIXPROTO_DEFINES from
+ .../install-tools/fixproto-defines.
+
+Sun Nov 12 19:31:27 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * comp-tools-verify (verify_cxx_initializers): delete argv,
+ argc declarations, add -static to compile line.
+ (verify_cxx_hello_world): delete argv, argc declarations, add
+ -static to compile line.
+
+Wed Sep 20 13:21:52 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New target, synonym for
+ realclean.
+
+Thu Sep 14 17:19:58 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Install.in (show_exec_prefix_msg): print out paths for
+ TCL_LIBRARY, TK_LIBRARY and GDBTK_FILENAME.
+
+Mon Aug 28 17:25:49 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Install.in (PATH): add /usr/ucb to $PATH (for SunOS 4.1.x).
+
+Tue Aug 15 21:51:58 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Install.in (guess_system): Match OSF/1 v3.x as the same as
+ v2.x--v2.x binaries are upward compatible.
+
+Tue Aug 15 21:46:54 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Install.in (guess_system): recognize HP 9000/800 systems as the
+ same as HP 9000/700 systems.
+
+Tue Aug 8 13:11:56 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * Install.in: For emacs, run show_emacs_alternate_msg and exit.
+ (show_emacs_alternate_msg): New message saying how emacs can't be
+ installed in an alternate prefix.
+
+Thu Jun 8 00:42:56 1995 Angela Marie Thomas <angela@cirdan.cygnus.com>
+
+ * subst-strings: change du commands to $BINDIR/. & $SRCDIR/. just
+ in case they are symlinks.
+
+Tue Apr 18 14:23:10 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * cdk-fix: Extracted table of targets that don't need their
+ headers fixed from gcc's configure script.
+
+ * cdk-fix, cdk-verify: Use ${HOST} instead of ||HOSTstr||
+
+ * cdk-fix, cdk-verify: New files, install script fragments used
+ for Cygnus Developer's Kit.
+
+ * Install.in (do_mkdir): New function.
+
+ * Install.in: Added support for --with and --without options.
+ Changed so that tape commands are not run when extracting
+ from a file.
+ (do_mt): Changed to take only one argument.
+
+Wed Mar 29 11:16:38 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Install.in: catch UNAME==alpha-dec-osf2.x and correct entry for
+ alpha-dec-osf1.x
+
+Fri Jan 27 12:04:29 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * subst-strings (mips-sgi-irix5): New entry in table.
+
+Thu Jan 19 12:15:44 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Install.in: Major rewrite, bundle dependent code (for example,
+ fixincludes for comp-tools) will be inserted into the Install
+ script when it is generated.
+
+Tue Jan 17 16:51:32 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * Makefile.in (Makefile): Rebuild using $(SHELL).
+
+Thu Nov 3 19:30:33 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (install-info): Depend on info.
+
+Fri Aug 19 16:16:38 1994 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Install.in: set $FIX_HEADER so fixproto can find fix-header.
+
+Fri May 6 16:18:58 1994 Jason Molenda (crash@sendai.cygnus.com)
+
+ * Makefile.in (install-info): add a semicolon in the if statement.
+
+Fri Apr 29 16:56:07 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * cfg-paper.texi: Update some outdated information.
+
+ * Makefile.in (install-info): Pass file, not directory, as last
+ arg to INSTALL_DATA.
+ (uninstall): New target.
+
+Thu Apr 28 14:42:22 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * configure.texi: Comment out @smallbook.
+
+ * Makefile.in: Define TEXI2DVI and TEXIDIR, and use the latter.
+ Remove info files in realclean, not clean, per coding standards.
+ Remove TeX output in clean.
+
+Tue Apr 26 17:18:03 1994 Jason Molenda (crash@sendai.cygnus.com)
+
+ * Install.in: fixincludes output is actually put in fixincludes.log,
+ but echo'ed messages claim it is fixinc.log. This is the same
+ messages as I logged in March 4 1994, but for some reason we found
+ the change hadn't been done. I'll have to dig through the logs
+ and find out what I really did do that day. :)
+
+Mon Apr 25 20:28:19 1994 Jason Molenda (crash@sendai.cygnus.com)
+
+ * Install.in: use eval to call do_mt() for Ultrix brokenness.
+
+Mon Apr 25 20:00:00 1994 Jason Molenda (crash@sendai.cygnus.com)
+
+ * Install.in(do_mt): exit with error status 1 if # of parameters
+ != 3.
+
+Mon Apr 25 19:42:36 1994 Jason Molenda (crash@sendai.cygnus.com)
+
+ * Install.in: lose TAPE_FORWARD and TAPE_REWIND, add do_mt()
+ to do all tape movement operations. Currently untested. Addresses
+ PR # 4886 from bull.
+
+ * Install.in: add 1994 to the copyright thing.
+
+Fri Apr 22 19:05:13 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * standards.texi: Update from FSF.
+
+Fri Apr 22 15:46:10 1994 Jason Molenda (crash@cygnus.com)
+
+ * Install.in: Add $DDOPTS, has ``bs=124b'' for all systems except
+ AIX (some versions of AIX don't understand bs=124b. Silly OS).
+
+Mon Apr 4 22:55:05 1994 Jason Molenda (crash@sendai.cygnus.com)
+
+ * Install.in: null out $TOOLS before adding stuff to it
+ non-destructively.
+
+Wed Mar 30 21:45:35 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * standards.texi: Fix typo.
+
+ * configure.texi, configure.man: Document --disable-.
+
+Mon Mar 28 13:22:15 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * standards.texi: Update from FSF.
+
+Sat Mar 26 09:21:44 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * standards.texi, make-stds.texi: Update from FSF.
+
+Fri Mar 25 22:59:45 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * configure.texi, configure.man: Document --enable-* options.
+
+Wed Mar 23 23:38:24 1994 Jason Molenda (crash@sendai.cygnus.com)
+
+ * Install.in: set CPP to be gcc -E for fixincludes.
+
+Wed Mar 23 13:42:48 1994 Jason Molenda (crash@sendai.cygnus.com)
+
+ * Install.in: set PATH to $PATH:/bin:/usr/bin so we can pick
+ up native tools even if the user doesn't have them in his
+ path.
+
+ * Install.in: ``hppa-1.1-hp-hpux'' -> ``hppa1.1-hp-hpux''.
+
+Tue Mar 15 22:09:20 1994 Jason Molenda (crash@sendai.cygnus.com)
+
+ * Install.in: TAPE_REWIND and TAPE_FORWARD variables for Unixunaware,
+ added switch statement to detect if system is Unixunaware.
+
+Fri Mar 4 12:10:30 1994 Jason Molenda (crash@sendai.cygnus.com)
+
+ * Install.in: fixincludes output is actually put in fixincludes.log,
+ but echo'ed messages claim it is fixinc.log.
+
+Wed Nov 3 02:58:02 1993 Jeffrey Osier (jeffrey@thepub.cygnus.com)
+
+ * subst-strings: output TEXBUNDLE for more install notes matching
+ * install-texi.in: PRMS info now exists
+
+Tue Oct 26 16:57:12 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * subst-strings: match solaris*. Also, add default case to catch
+ and error out for unrecognized systems.
+
+Thu Aug 19 18:21:31 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * Install.in: handle the new fixproto work
+
+Mon Jul 19 12:05:41 1993 david d `zoo' zuhn (zoo@cirdan.cygnus.com)
+
+ * Install.in: remove "MT=tctl" for AIX (not needed, and barely
+ worked anyway)
+
+Mon Jun 14 19:09:22 1993 Jeffrey Osier (jeffrey@cygnus.com)
+
+ * subst-strings: changed HOST to recognize Solaris for install notes
+
+Thu Jun 10 16:01:25 1993 Jeffrey Osier (jeffrey@cygnus.com)
+
+ * dos-inst.texi: new file.
+
+Wed Jun 9 19:23:59 1993 Jeffrey Osier (jeffrey@rtl.cygnus.com)
+
+ * install-texi.in: added conditionals (nearly complete)
+ cleaned up
+ added support for other releases (not done)
+
+Wed Jun 9 15:53:58 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (install-info): Use INSTALL_DATA.
+ ({dist,real}clean): Also delete Makefile and config.status.
+
+Fri Jun 4 17:09:56 1993 Jeffrey Osier (jeffrey@cygnus.com)
+
+ * subst-strings: added data for OS_STRING
+
+ * subst-strings: added support for OS_STRING
+
+Thu Jun 3 00:37:01 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Install.in: pull COPYING and COPYING.LIB off of the tape
+
+Tue Jun 1 16:52:08 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * subst-strings: replace RELEASE_DIR too
+
+Mon Mar 22 23:55:27 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: add installcheck target
+
+Wed Mar 17 02:21:15 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Install.in: fix 'source only' extraction bug where it looked for
+ the src dir under H-<host>/src instead of src; also remove stray
+ reference to EMACSHIBIN
+
+Mon Mar 15 01:25:45 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * make-stds.texi: added 'installcheck' to the standard targets
+
+Tue Mar 9 19:48:28 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * standards.texi: added INFO-DIR-ENTRY, updated version from the FSF
+
+Tue Feb 9 12:40:23 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (standards.info): Added -I$(srcdir) to find
+ make-stds.texi.
+
+Mon Feb 1 16:32:56 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * standards.texi: updated to latest FSF version, which includes:
+
+ * make-stds.texi: new file
+
+Mon Nov 30 01:31:40 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * install-texi.in, relnotes.texi, intro.texi: changed Cygnus phone
+ numbers from the old Palo Alto ones to the new Mtn. View numbers
+
+Mon Nov 16 16:50:43 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: define $(RM) to "rm -f"
+
+Sun Oct 11 16:05:48 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * intro.texi: added INFO-DIR-ENTRY
+
diff --git a/gnu/usr.bin/binutils/include/coff/aux-coff.h b/gnu/usr.bin/binutils/include/coff/aux-coff.h
new file mode 100644
index 00000000000..c89c124d3e0
--- /dev/null
+++ b/gnu/usr.bin/binutils/include/coff/aux-coff.h
@@ -0,0 +1,31 @@
+/* Modifications of internal.h and m68k.h needed by A/UX
+ Suggested by Ian Lance Taylor <ian@cygnus.com> */
+
+#ifndef GNU_COFF_AUX_H
+#define GNU_COFF_AUX_H 1
+
+#include "coff/internal.h"
+#include "coff/m68k.h"
+
+/* Section contains 64-byte padded pathnames of shared libraries */
+#undef STYP_LIB
+#define STYP_LIB 0x200
+
+/* Section contains shared library initialization code */
+#undef STYP_INIT
+#define STYP_INIT 0x400
+
+/* Section contains .ident information */
+#undef STYP_IDENT
+#define STYP_IDENT 0x800
+
+/* Section types used by bfd and gas not defined (directly) by A/UX */
+#undef STYP_OVER
+#define STYP_OVER 0
+#undef STYP_INFO
+#define STYP_INFO STYP_IDENT
+
+/* Traditional name of the section tagged with STYP_LIB */
+#define _LIB ".lib"
+
+#endif /* GNU_COFF_AUX_H */
diff --git a/gnu/usr.bin/binutils/include/elf/sparc.h b/gnu/usr.bin/binutils/include/elf/sparc.h
new file mode 100644
index 00000000000..399b506ad7a
--- /dev/null
+++ b/gnu/usr.bin/binutils/include/elf/sparc.h
@@ -0,0 +1,71 @@
+/* SPARC ELF support for BFD.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ By Doug Evans, Cygnus Support, <dje@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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. */
+
+#ifndef _ELF_SPARC_H
+#define _ELF_SPARC_H
+
+/* Processor specific flags for the ELF header e_flags field. */
+
+/* These are defined by Sun. */
+
+#define EF_SPARC_32PLUS_MASK 0xffff00 /* bits indicating V8+ type */
+#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */
+
+/* Relocation types. */
+
+enum elf_sparc_reloc_type {
+ R_SPARC_NONE = 0,
+ R_SPARC_8, R_SPARC_16, R_SPARC_32,
+ R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32,
+ R_SPARC_WDISP30, R_SPARC_WDISP22,
+ R_SPARC_HI22, R_SPARC_22,
+ R_SPARC_13, R_SPARC_LO10,
+ R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22,
+ R_SPARC_PC10, R_SPARC_PC22,
+ R_SPARC_WPLT30,
+ R_SPARC_COPY,
+ R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT,
+ R_SPARC_RELATIVE,
+ R_SPARC_UA32,
+
+ /* ??? These 6 relocs are new but not currently used. For binary
+ compatility in the sparc64-elf toolchain, we leave them out.
+ A non-binary upward compatible change is expected for sparc64-elf. */
+#ifndef SPARC64_OLD_RELOCS
+ /* ??? New relocs on the UltraSPARC. Not sure what they're for yet. */
+ R_SPARC_PLT32, R_SPARC_HIPLT22, R_SPARC_LOPLT10,
+ R_SPARC_PCPLT32, R_SPARC_PCPLT22, R_SPARC_PCPLT10,
+#endif
+
+ /* v9 relocs */
+ R_SPARC_10, R_SPARC_11, R_SPARC_64,
+ R_SPARC_OLO10, R_SPARC_HH22, R_SPARC_HM10, R_SPARC_LM22,
+ R_SPARC_PC_HH22, R_SPARC_PC_HM10, R_SPARC_PC_LM22,
+ R_SPARC_WDISP16, R_SPARC_WDISP19,
+ R_SPARC_GLOB_JMP,
+ R_SPARC_7,
+ R_SPARC_5, R_SPARC_6,
+
+ R_SPARC_max
+};
+
+#endif /* _ELF_SPARC_H */
diff --git a/gnu/usr.bin/binutils/libiberty/atexit.c b/gnu/usr.bin/binutils/libiberty/atexit.c
new file mode 100644
index 00000000000..4463cb69501
--- /dev/null
+++ b/gnu/usr.bin/binutils/libiberty/atexit.c
@@ -0,0 +1,14 @@
+/* Wrapper to implement ANSI C's atexit using SunOS's on_exit. */
+/* This function is in the public domain. --Mike Stump. */
+
+#ifndef NEED_on_exit
+int
+atexit(f)
+ void (*f)();
+{
+ /* If the system doesn't provide a definition for atexit, use on_exit
+ if the system provides that. */
+ on_exit (f, 0);
+ return 0;
+}
+#endif
diff --git a/gnu/usr.bin/binutils/libiberty/choose-temp.c b/gnu/usr.bin/binutils/libiberty/choose-temp.c
new file mode 100644
index 00000000000..b687729e2f6
--- /dev/null
+++ b/gnu/usr.bin/binutils/libiberty/choose-temp.c
@@ -0,0 +1,144 @@
+/* Utility to pick a temporary filename prefix.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If not,
+write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This file exports one function: choose_temp_base. */
+
+/* This file lives in at least two places: libiberty and gcc.
+ Don't change one without the other. */
+
+#if ! defined (_WIN32) && ! defined (NO_SYS_FILE_H)
+#include <sys/types.h>
+#include <sys/file.h> /* May get R_OK, etc. on some systems. */
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#endif
+
+#include <stdio.h> /* May get P_tmpdir. */
+
+#ifdef IN_GCC
+#include "config.h"
+#include "gansidecl.h"
+extern char *xmalloc ();
+#else
+#include "ansidecl.h"
+#include "libiberty.h"
+#if defined (__MSDOS__) || defined (_WIN32)
+#define DIR_SEPARATOR '\\'
+#endif
+#endif
+
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
+/* On MSDOS, write temp files in current dir
+ because there's no place else we can expect to use. */
+/* ??? Although the current directory is tried as a last resort,
+ this is left in so that on MSDOS it is prefered to /tmp on the
+ off chance that someone requires this, since that was the previous
+ behaviour. */
+#ifdef __MSDOS__
+#ifndef P_tmpdir
+#define P_tmpdir "."
+#endif
+#endif
+
+/* Name of temporary file.
+ mktemp requires 6 trailing X's. */
+#define TEMP_FILE "ccXXXXXX"
+
+/* Subroutine of choose_temp_base.
+ If BASE is non-NULL, returh it.
+ Otherwise it checks if DIR is a usable directory.
+ If success, DIR is returned.
+ Otherwise NULL is returned. */
+
+static char *
+try (dir, base)
+ char *dir, *base;
+{
+ if (base != 0)
+ return base;
+ if (dir != 0
+ && access (dir, R_OK | W_OK) == 0)
+ return dir;
+ return 0;
+}
+
+/* Return a prefix for temporary file names or NULL if unable to find one.
+ The current directory is chosen if all else fails so the program is
+ exited if a temporary directory can't be found (mktemp fails).
+ The buffer for the result is obtained with xmalloc. */
+
+char *
+choose_temp_base ()
+{
+ char *base = 0;
+ char *temp_filename;
+ int len;
+ static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
+ static char usrtmp[] = { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
+
+#ifndef MPW
+ base = try (getenv ("TMPDIR"), base);
+ base = try (getenv ("TMP"), base);
+ base = try (getenv ("TEMP"), base);
+
+#ifdef P_tmpdir
+ base = try (P_tmpdir, base);
+#endif
+
+ /* Try /usr/tmp, then /tmp. */
+ base = try (usrtmp, base);
+ base = try (tmp, base);
+
+ /* If all else fails, use the current directory! */
+ if (base == 0)
+ base = ".";
+
+#else /* MPW */
+ base = ":";
+#endif
+
+ len = strlen (base);
+ if (len == 0)
+ abort ();
+ temp_filename = xmalloc (len + 1 /*DIR_SEPARATOR*/
+ + strlen (TEMP_FILE) + 1);
+ strcpy (temp_filename, base);
+
+#ifndef MPW
+ if (temp_filename[len-1] != '/'
+ && temp_filename[len-1] != DIR_SEPARATOR)
+ temp_filename[len++] = DIR_SEPARATOR;
+#else /* MPW */
+ if (temp_filename[len-1] != ':')
+ temp_filename[len++] = ':';
+#endif /* MPW */
+ strcpy (temp_filename + len, TEMP_FILE);
+
+ mktemp (temp_filename);
+ if (strlen (temp_filename) == 0)
+ abort ();
+ return temp_filename;
+}
diff --git a/gnu/usr.bin/binutils/libiberty/xstrdup.c b/gnu/usr.bin/binutils/libiberty/xstrdup.c
new file mode 100644
index 00000000000..9d08bc70405
--- /dev/null
+++ b/gnu/usr.bin/binutils/libiberty/xstrdup.c
@@ -0,0 +1,17 @@
+/* xstrdup.c -- Duplicate a string in memory, using xmalloc.
+ This trivial function is in the public domain.
+ Ian Lance Taylor, Cygnus Support, December 1995. */
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+char *
+xstrdup (s)
+ const char *s;
+{
+ char *ret;
+
+ ret = xmalloc (strlen (s) + 1);
+ strcpy (ret, s);
+ return ret;
+}
diff --git a/gnu/usr.bin/binutils/symlink-tree b/gnu/usr.bin/binutils/symlink-tree
new file mode 100644
index 00000000000..bd35f8f6401
--- /dev/null
+++ b/gnu/usr.bin/binutils/symlink-tree
@@ -0,0 +1,46 @@
+#!/bin/sh
+# Create a symlink tree.
+#
+# Syntax: symlink-tree srcdir "ignore1 ignore2 ..."
+#
+# where srcdir is the directory to create a symlink tree to,
+# and "ignoreN" is a list of files/directories to ignore.
+
+prog=$0
+srcdir=$1
+ignore="$2"
+
+ignore_additional=". .. CVS"
+
+# If we were invoked with a relative path name, adjust ${prog} to work
+# in subdirs.
+case ${prog} in
+/*) ;;
+*) prog=../${prog} ;;
+esac
+
+# Set newsrcdir to something subdirectories can use.
+case ${srcdir} in
+/*) newsrcdir=${srcdir} ;;
+*) newsrcdir=../${srcdir} ;;
+esac
+
+for f in `ls -a ${srcdir}`; do
+ if [ -d ${srcdir}/$f ]; then
+ found=
+ for i in ${ignore} ${ignore_additional}; do
+ if [ "$f" = "$i" ]; then
+ found=yes
+ fi
+ done
+ if [ -z "${found}" ]; then
+ if [ -d $f ]; then true; else mkdir $f; fi
+ (cd $f; ${prog} ${newsrcdir}/$f "${ignore}")
+ fi
+ else
+ rm -f $f
+ ln -s ${srcdir}/$f .
+ fi
+done
+
+exit 0