diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-06-07 11:08:08 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-06-07 11:08:08 +0000 |
commit | 5e8f84744ab42cf6648e9cc6fa9aa4f6a713a484 (patch) | |
tree | 95c644446f498bed99df8b6b2356775209a34a43 /gnu/usr.bin/binutils | |
parent | d671f825bb877aa8089bd042d91e61f7e3160825 (diff) |
(Correct) Import of Cygnus binutils snapshot taken 960607
Diffstat (limited to 'gnu/usr.bin/binutils')
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 = ⊤ + + 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, §ype) + || ! 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 |