diff options
-rw-r--r-- | binutils/.Sanitize | 1 | ||||
-rw-r--r-- | binutils/ChangeLog | 41 | ||||
-rw-r--r-- | binutils/Makefile.in | 257 | ||||
-rw-r--r-- | binutils/budbg.h | 11 | ||||
-rw-r--r-- | binutils/ieee.c | 2178 |
5 files changed, 2383 insertions, 105 deletions
diff --git a/binutils/.Sanitize b/binutils/.Sanitize index be71ab7..a1bf341 100644 --- a/binutils/.Sanitize +++ b/binutils/.Sanitize @@ -57,6 +57,7 @@ defparse.y deflex.l filemode.c gmalloc.c +ieee.c is-ranlib.c is-strip.c mac-binutils.r diff --git a/binutils/ChangeLog b/binutils/ChangeLog index bf952fe..4b7d71a 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,44 @@ +Thu Jan 4 16:31:21 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c: New file with code to read IEEE debugging information. + * budbg.h (parse_ieee): Declare. + * rddbg.c (read_debugging_info): Handle IEEE flavour files. + (read_ieee_debugging_info): New static function. + * Makefile.in: Rebuild dependencies. + (CFILES): Add ieee.c. + (OBJDUMP_OBJS): Add ieee.o. + + * bucomm.h (xrealloc): Change type of first parameter from char * + to PTR. + +Tue Jan 2 17:44:07 1996 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in: Add targets to automatically rebuild dependencies. + Remove targets which just listed dependencies of .o files. + (DEP): New variable. + (HFILES, GENERATED_HFILES): New variables. + (CFILES, GENERATED_CFILES): New variables. + (underscore.c): Don't do anything, just depend upon stamp-under. + (stamp-under): New target; do what underscore.c used to do. + (nlmconv.o): Depend upon sym.h and ecoff.h. + (.dep, .dep1, dep.sed, dep, dep-in): New targets. + (stage1, stage2, stage3, against, comparison): Remove. + (de-stage1, de-stage2, de-stage3): Remove. + (clean, distclean): Remove stamp-under and dep.sed. + * dep-in.sed: New file. + + Implement generic debugging support. Implement a stabs reader and + a generic printer. + * budbg.h, debug.c, debug.h, prdbg.c, rddbg.c, stabs.c: New files. + * objdump.c: Include "debug.h" and "budbg.h". + (dump_debugging): New global variable. + (usage): Mention --debugging. + (long_options): Add "debugging". + (display_bfd): Handle --debugging. + * Makefile.in (OBJDUMP_OBJS): New variable. + ($(OBJDUMP_PROG)): Use $(OBJDUMP_OBJS). + * binutils.texi, objdump.1: Document --debugging. + Sat Dec 30 09:59:51 1995 Jeffrey A Law (law@cygnus.com) * nm.c ( long_options): Add "--defined-only" option. diff --git a/binutils/Makefile.in b/binutils/Makefile.in index 67050bd..6801d56 100644 --- a/binutils/Makefile.in +++ b/binutils/Makefile.in @@ -1,5 +1,5 @@ # Makefile for GNU binary-file utilities -# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. +# Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. # This file is part of GNU binutils. @@ -107,8 +107,6 @@ DLLTOOL_PROG=dlltool SRCONV_PROG=srconv sysdump coffdump - - MANPAGES= ar nm objdump ranlib size strings strip objcopy nlmconv PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @@ -125,9 +123,24 @@ BASEDIR = $(srcdir)/.. BFDDIR = $(BASEDIR)/bfd INCDIR = $(BASEDIR)/include INCLUDES = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) +DEP = mkdep ALL_CFLAGS = $(INCLUDES) @HDEFINES@ $(CFLAGS) +HFILES = arsup.h bucomm.h budbg.h coffgrok.h debug.h nlmconv.h + +GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h + +CFILES = ar.c arsup.c bucomm.c coffdump.c coffgrok.c debug.c dlltool.c \ + filemode.c ieee.c is-ranlib.c is-strip.c maybe-ranlib.c \ + maybe-strip.c nlmconv.c nm.c not-ranlib.c not-strip.c \ + objcopy.c objdump.c prdbg.c rddbg.c size.c srconv.c stabs.c \ + strings.c sysdump.c version.c + +GENERATED_CFILES = \ + underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \ + defparse.c deflex.c nlmheader.c + .c.o: $(CC) -c $(ALL_CFLAGS) $< @@ -255,14 +268,18 @@ $(STRIP_PROG): $(ADDL_LIBS) objcopy.o is-strip.o $(BFD) $(NM_PROG): $(ADDL_LIBS) nm.o $(BFD) $(CC) $(CFLAGS) $(LDFLAGS) -o $(NM_PROG) nm.o $(ADDL_LIBS) $(EXTRALIBS) -$(OBJDUMP_PROG): $(ADDL_LIBS) objdump.o $(BFD) $(OPCODES) - $(CC) $(CFLAGS) $(LDFLAGS) -o $(OBJDUMP_PROG) objdump.o $(OPCODES) $(ADDL_LIBS) $(EXTRALIBS) +OBJDUMP_OBJS = objdump.o rddbg.o debug.o stabs.o ieee.o prdbg.o + +$(OBJDUMP_PROG): $(ADDL_LIBS) $(OBJDUMP_OBJS) $(BFD) $(OPCODES) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(OBJDUMP_PROG) $(OBJDUMP_OBJS) $(OPCODES) $(ADDL_LIBS) $(EXTRALIBS) + +underscore.c: stamp-under ; @true -underscore.c: Makefile - rm -f underscore.c +stamp-under: Makefile echo '/*WARNING: This file is automatically generated!*/' >underscore.t echo "int prepends_underscore = @UNDERSCORE@;" >>underscore.t - mv -f underscore.t underscore.c + $(srcdir)/../move-if-change underscore.t underscore.c + touch stamp-under version.o: version.c Makefile $(CC) -DVERSION='"$(VERSION)"' $(ALL_CFLAGS) -c $(srcdir)/version.c @@ -352,9 +369,6 @@ sysinfo.o: sysinfo.c $(CC_FOR_BUILD) -c -I. $(CFLAGS) $(srcdir)/sysinfo.c ; \ fi -srconv.o: srconv.c sysroff.h sysroff.c coffgrok.h $(INCDIR)/coff/internal.h \ - ../bfd/libcoff.h config.h - srconv: srconv.o coffgrok.o $(ADDL_LIBS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ srconv.o coffgrok.o $(ADDL_LIBS) $(EXTRALIBS) @@ -378,8 +392,6 @@ dlltool.o:dlltool.c coffdump: coffdump.o coffgrok.o $(ADDL_LIBS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ coffdump.o coffgrok.o $(ADDL_LIBS) $(EXTRALIBS) -sysdump.o: sysdump.c sysroff.h sysroff.c bucomm.h config.h - sysdump: sysdump.o $(ADDL_LIBS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ sysdump.o $(ADDL_LIBS) $(EXTRALIBS) @@ -390,93 +402,45 @@ nlmheader.c: nlmheader.y sysinfo.c rm -f nlmheader.c mv -f y.tab.c nlmheader.c -nlmconv.o: nlmconv.c +# coff/sym.h and coff/ecoff.h won't be found by the automatic dependency +# scripts, since they are only included conditionally. +nlmconv.o: nlmconv.c $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h ldname=`echo ld | sed '$(program_transform_name)'`; \ $(CC) -c -DLD_NAME="\"$${ldname}\"" @NLMCONV_DEFS@ $(ALL_CFLAGS) $(srcdir)/nlmconv.c $(NLMCONV_PROG): nlmconv.o nlmheader.o $(ADDL_LIBS) $(BFD) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ nlmconv.o nlmheader.o $(ADDL_LIBS) $(EXTRALIBS) -# This list of dependencies was generated by doing a make with gcc -MM -# saving the output in a file and removing the gcc commands -# changing "../../devo/binutils/../bfd" to "$(BFDDIR)" -# removing "../../devo/binutils/" -# changing "../include" to "$(INCDIR)" - -bucomm.o: bucomm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ - $(INCDIR)/obstack.h \ - $(INCDIR)/fopen-same.h bucomm.h config.h -filemode.o: filemode.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ - $(INCDIR)/obstack.h \ - $(INCDIR)/fopen-same.h -size.o: size.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ - $(INCDIR)/obstack.h \ - $(INCDIR)/fopen-same.h $(INCDIR)/getopt.h config.h -objdump.o: objdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ - $(INCDIR)/obstack.h \ - $(INCDIR)/fopen-same.h $(INCDIR)/getopt.h \ - $(INCDIR)/dis-asm.h $(INCDIR)/aout/aout64.h \ - $(INCDIR)/elf/internal.h $(INCDIR)/aout/stab.def config.h -nm.o: nm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ - $(INCDIR)/obstack.h \ - $(INCDIR)/fopen-same.h bucomm.h config.h $(INCDIR)/getopt.h \ - $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def \ - $(INCDIR)/aout/ranlib.h $(INCDIR)/demangle.h -ar.o: ar.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ - $(INCDIR)/obstack.h \ - $(INCDIR)/fopen-same.h bucomm.h config.h $(INCDIR)/aout/ar.h \ - $(BFDDIR)/libbfd.h arsup.h -arparse.o: arparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ - $(INCDIR)/obstack.h arsup.h -arlex.o: arlex.c ./arparse.h -not-ranlib.o: not-ranlib.c -arsup.o: arsup.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ - $(INCDIR)/obstack.h arsup.h bucomm.h config.h -strings.o: strings.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ - $(INCDIR)/obstack.h bucomm.h config.h -objcopy.o: objcopy.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ - $(INCDIR)/obstack.h \ - $(INCDIR)/fopen-same.h bucomm.h config.h -is-strip.o: is-strip.c -is-ranlib.o: is-ranlib.c -not-strip.o: not-strip.c -nlmheader.o: nlmheader.c ../bfd/bfd.h \ - $(INCDIR)/fopen-same.h bucomm.h config.h \ - $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h nlmconv.h -nlmconv.o: nlmconv.c ../bfd/bfd.h $(INCDIR)/libiberty.h \ - $(INCDIR)/fopen-same.h bucomm.h config.h \ - $(BFDDIR)/libnlm.h $(INCDIR)/nlm/common.h \ - $(INCDIR)/nlm/internal.h $(INCDIR)/nlm/external.h nlmconv.h \ - $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h - -stage1: force - - mkdir stage1 - - mv -f $(STAGESTUFF) stage1 - -stage2: force - - mkdir stage2 - - mv -f $(STAGESTUFF) stage2 - -stage3: force - - mkdir stage3 - - mv -f $(STAGESTUFF) stage3 - -against=stage2 - -comparison: force - for i in $(STAGESTUFF) ; do cmp $$i $(against)/$$i ; done - -de-stage1: force - - (cd stage1 ; mv -f * ..) - - rmdir stage1 - -de-stage2: force - - (cd stage2 ; mv -f * ..) - - rmdir stage2 - -de-stage3: force - - (cd stage3 ; mv -f * ..) - - rmdir stage3 +# Targets to rebuild dependencies in this Makefile. +# Have to get rid of .dep1 here so that "$?" later includes all of $(CFILES). +.dep: dep.sed $(CFILES) $(HFILES) $(GENERATED_CFILES) $(GENERATED_HFILES) config.h + rm -f .dep1 + $(MAKE) DEP=$(DEP) .dep1 + sed -f dep.sed <.dep1 >.dep + +# This rule really wants a mkdep that runs "gcc -MM". +.dep1: $(CFILES) $(GENERATED_CFILES) + rm -f .dep2 + echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep2 + $(DEP) -f .dep2 $(ALL_CFLAGS) $? + $(srcdir)/../move-if-change .dep2 .dep1 + +dep.sed: dep-in.sed config.status + sed <$(srcdir)/dep-in.sed >dep.sed \ + -e 's!@INCDIR@!$(INCDIR)!' \ + -e 's!@SRCDIR@!$(srcdir)!' + +dep: .dep + sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < Makefile > tmp-Makefile + cat .dep >> tmp-Makefile + $(srcdir)/../move-if-change tmp-Makefile Makefile + +dep-in: .dep + sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.in > tmp-Makefile.in + cat .dep >> tmp-Makefile.in + $(srcdir)/../move-if-change tmp-Makefile.in $(srcdir)/Makefile.in + +.PHONY: dep dep-in ### # DOCUMENTATION TARGETS @@ -561,11 +525,13 @@ mostlyclean: -rm -f *.o *~ \#* core binutils.?? binutils.??? y.output config.log -rm -rf tmpdir clean: mostlyclean - -rm -f $(PROGS) underscore.c sysroff sysroff.c sysroff.h sysinfo + -rm -f $(PROGS) $(DEMANGLER_PROG).1 stamp-under + -rm -f underscore.c sysroff sysroff.c sysroff.h sysinfo dep.sed distclean: - -rm -f Makefile config.status *.o *~ \#* core y.* \ - binutils.?? binutils.??s binutils.aux binutils.log binutils.toc + -rm -f Makefile config.status *.o *~ \#* core y.* + -rm -f binutils.?? binutils.??s binutils.aux binutils.log binutils.toc -rm -f $(PROGS) underscore.c config.h stamp-h config.cache config.log + -rm -f dep.sed stamp-under maintainer-clean realclean: clean distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." @@ -685,8 +651,95 @@ stamp-h: config.in config.status config.status: configure $(SHELL) ./config.status --recheck -### Local Variables: *** -### mode:fundamental *** -### page-delimiter: "^#" *** -### End: *** -### end of file +# What appears below is generated by a hacked mkdep using gcc -MM. + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + +ar.o: ar.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/obstack.h \ + $(INCDIR)/libiberty.h $(INCDIR)/progress.h bucomm.h \ + config.h $(INCDIR)/fopen-same.h $(INCDIR)/aout/ar.h \ + ../bfd/libbfd.h arsup.h +arsup.o: arsup.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h arsup.h $(INCDIR)/libiberty.h bucomm.h \ + config.h $(INCDIR)/fopen-same.h +bucomm.o: bucomm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h $(INCDIR)/libiberty.h bucomm.h \ + config.h $(INCDIR)/fopen-same.h +coffdump.o: coffdump.c coffgrok.h bucomm.h config.h \ + $(INCDIR)/fopen-same.h +coffgrok.o: coffgrok.c bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/coff/internal.h ../bfd/libcoff.h $(INCDIR)/bfdlink.h \ + coffgrok.h +debug.o: debug.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h debug.h +dlltool.o: dlltool.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h $(INCDIR)/libiberty.h bucomm.h \ + config.h $(INCDIR)/fopen-same.h $(INCDIR)/getopt.h \ + $(INCDIR)/demangle.h +filemode.o: filemode.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h +ieee.o: ieee.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/obstack.h \ + $(INCDIR)/ieee.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h debug.h budbg.h +is-ranlib.o: is-ranlib.c +is-strip.o: is-strip.c +maybe-ranlib.o: maybe-ranlib.c +maybe-strip.o: maybe-strip.c +nlmconv.o: nlmconv.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h $(INCDIR)/libiberty.h bucomm.h \ + config.h $(INCDIR)/fopen-same.h ../bfd/libnlm.h $(INCDIR)/nlm/common.h \ + $(INCDIR)/nlm/internal.h $(INCDIR)/nlm/external.h nlmconv.h +nm.o: nm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/obstack.h \ + $(INCDIR)/progress.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/getopt.h $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def \ + $(INCDIR)/aout/ranlib.h $(INCDIR)/demangle.h $(INCDIR)/libiberty.h +not-ranlib.o: not-ranlib.c +not-strip.o: not-strip.c +objcopy.o: objcopy.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h $(INCDIR)/progress.h bucomm.h config.h \ + $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h +objdump.o: objdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h $(INCDIR)/getopt.h $(INCDIR)/progress.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/dis-asm.h \ + $(INCDIR)/libiberty.h debug.h budbg.h $(INCDIR)/aout/aout64.h \ + $(INCDIR)/aout/stab.def +prdbg.o: prdbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h debug.h budbg.h +rddbg.o: rddbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h debug.h budbg.h +size.o: size.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/obstack.h \ + $(INCDIR)/getopt.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h +srconv.o: srconv.c bucomm.h config.h $(INCDIR)/fopen-same.h \ + sysroff.h coffgrok.h $(INCDIR)/coff/internal.h ../bfd/libcoff.h \ + $(INCDIR)/bfdlink.h sysroff.c +stabs.o: stabs.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h debug.h budbg.h $(INCDIR)/aout/aout64.h \ + $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def +strings.o: strings.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h +sysdump.o: sysdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + sysroff.h sysroff.c +version.o: version.c +underscore.o: underscore.c +arparse.o: arparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + arsup.h +arlex.o: arlex.c arparse.h +sysroff.o: sysroff.c +sysinfo.o: sysinfo.c +syslex.o: syslex.c sysinfo.h +defparse.o: defparse.c +deflex.o: deflex.c defparse.h +nlmheader.o: nlmheader.c ../bfd/bfd.h $(INCDIR)/obstack.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/nlm/common.h \ + $(INCDIR)/nlm/internal.h nlmconv.h + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/binutils/budbg.h b/binutils/budbg.h index e63841e..aec0bf2 100644 --- a/binutils/budbg.h +++ b/binutils/budbg.h @@ -1,5 +1,5 @@ /* budbg.c -- Interfaces to the generic debugging information routines. - Copyright (C) 1995 Free Software Foundation, Inc. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. Written by Ian Lance Taylor <ian@cygnus.com>. This file is part of GNU Binutils. @@ -26,7 +26,7 @@ /* Routine used to read generic debugging information. */ -extern PTR read_debugging_info PARAMS ((bfd *)); +extern PTR read_debugging_info PARAMS ((bfd *, asymbol **, long)); /* Routine used to print generic debugging information. */ @@ -34,10 +34,15 @@ extern boolean print_debugging_info PARAMS ((FILE *, PTR)); /* Routines used to read stabs information. */ -extern PTR start_stab PARAMS ((PTR)); +extern PTR start_stab PARAMS ((PTR, boolean)); extern boolean finish_stab PARAMS ((PTR, PTR)); extern boolean parse_stab PARAMS ((PTR, PTR, int, int, bfd_vma, const char *)); +/* Routine used to read IEEE information. */ + +extern boolean parse_ieee + PARAMS ((PTR, bfd *, const bfd_byte *, bfd_size_type)); + #endif diff --git a/binutils/ieee.c b/binutils/ieee.c new file mode 100644 index 0000000..9f95d5c --- /dev/null +++ b/binutils/ieee.c @@ -0,0 +1,2178 @@ +/* ieee.c -- Write out 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; +}; + +/* 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; +}; + +/* 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; + /* If this is a bitfield, this is the size in bits. If this is not + a bitfield, this is zero. */ + unsigned long bitsize; + /* If this is a function type ('x' or 'X') this is the return type. */ + debug_type return_type; +}; + +/* 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]; +}; + +static void ieee_error + PARAMS ((bfd *, const bfd_byte *, const bfd_byte *, const char *)); +static void ieee_eof PARAMS ((bfd *)); +static char *savestring PARAMS ((const char *, unsigned long)); +static boolean ieee_read_number + PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *, + bfd_vma *)); +static boolean ieee_read_optional_number + PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *, + bfd_vma *, boolean *)); +static boolean ieee_read_id + PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *, + const char **, unsigned long *)); +static boolean ieee_read_optional_id + PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *, + const char **, unsigned long *, boolean *)); +static boolean ieee_read_expression + PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *, + bfd_vma *)); +static debug_type ieee_builtin_type + PARAMS ((PTR, bfd *, struct ieee_types *, const bfd_byte *, + const bfd_byte *, unsigned int)); +static boolean ieee_read_type_index + PARAMS ((PTR, bfd *, struct ieee_types *, const bfd_byte *, + const bfd_byte **, const bfd_byte *, debug_type *)); +static int ieee_regno_to_gen PARAMS ((bfd *, int)); +static boolean parse_ieee_bb + PARAMS ((PTR, bfd *, struct ieee_types *, struct ieee_blockstack *, + const bfd_byte *, const bfd_byte **, const bfd_byte *)); +static boolean parse_ieee_be + PARAMS ((PTR, bfd *, struct ieee_blockstack *, const bfd_byte *, + const bfd_byte **, const bfd_byte *)); +static boolean parse_ieee_nn + PARAMS ((PTR, bfd *, struct ieee_vars *, const bfd_byte *, + const bfd_byte **, const bfd_byte *)); +static boolean parse_ieee_ty + PARAMS ((PTR, bfd *, struct ieee_types *, struct ieee_vars *, + const bfd_byte *, const bfd_byte **, const bfd_byte *)); +static boolean parse_ieee_atn + PARAMS ((PTR, bfd *, struct ieee_types *, struct ieee_vars *, int, + const bfd_byte *, const bfd_byte **, const bfd_byte *)); +static boolean ieee_require_asn + PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *, + bfd_vma *)); + +/* Report an error in the IEEE debugging information. */ + +static void +ieee_error (abfd, bytes, p, s) + bfd *abfd; + const bfd_byte *bytes; + const bfd_byte *p; + const char *s; +{ + if (p != NULL) + fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (abfd), + (unsigned long) (p - bytes), s, *p); + else + fprintf (stderr, "%s: %s\n", bfd_get_filename (abfd), s); +} + +/* Report an unexpected EOF in the IEEE debugging information. */ + +static void +ieee_eof (abfd) + bfd *abfd; +{ + ieee_error (abfd, (const bfd_byte *) NULL, (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 (abfd, bytes, pp, pend, pv) + bfd *abfd; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; + bfd_vma *pv; +{ + return ieee_read_optional_number (abfd, bytes, pp, pend, 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 (abfd, bytes, pp, pend, pv, ppresent) + bfd *abfd; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; + bfd_vma *pv; + boolean *ppresent; +{ + ieee_record_enum_type b; + + if (*pp >= pend) + { + if (ppresent != NULL) + { + *ppresent = false; + return true; + } + ieee_eof (abfd); + 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 >= pend) + { + ieee_eof (abfd); + 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 (abfd, bytes, *pp - 1, "invalid number"); + return false; +} + +/* Read a required string from an IEEE file. */ + +static boolean +ieee_read_id (abfd, bytes, pp, pend, pname, pnamlen) + bfd *abfd; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; + const char **pname; + unsigned long *pnamlen; +{ + return ieee_read_optional_id (abfd, bytes, pp, pend, 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 (abfd, bytes, pp, pend, pname, pnamlen, ppresent) + bfd *abfd; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; + const char **pname; + unsigned long *pnamlen; + boolean *ppresent; +{ + bfd_byte b; + unsigned long len; + + if (*pp >= pend) + { + ieee_eof (abfd); + 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 (abfd, bytes, *pp - 1, "invalid string length"); + return false; + } + + if ((unsigned long) (pend - *pp) < len) + { + ieee_eof (abfd); + 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 (abfd, bytes, pp, pend, pv) + bfd *abfd; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; + 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 (abfd, bytes, pp, pend, &val, &present)) + return false; + + if (present) + { + if (esp - expr_stack >= EXPR_STACK_SIZE) + { + ieee_error (abfd, bytes, 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 (abfd, bytes, start, + "unsupported IEEE expression operator"); + break; + + case ieee_variable_R_enum: + { + bfd_vma indx; + asection *s; + + if (! ieee_read_number (abfd, bytes, pp, pend, &indx)) + return false; + for (s = abfd->sections; s != NULL; s = s->next) + if ((bfd_vma) s->target_index == indx) + break; + if (s == NULL) + { + ieee_error (abfd, bytes, start, "unknown section"); + return false; + } + + if (esp - expr_stack >= EXPR_STACK_SIZE) + { + ieee_error (abfd, bytes, start, "expression stack overflow"); + return false; + } + + *esp++ = bfd_get_section_vma (abfd, s); + } + break; + + case ieee_function_plus_enum: + case ieee_function_minus_enum: + { + bfd_vma v1, v2; + + if (esp - expr_stack < 2) + { + ieee_error (abfd, bytes, start, "expression stack underflow"); + return false; + } + + v1 = *--esp; + v2 = *--esp; + *esp++ = v1 + v2; + } + break; + } + } + + if (esp - 1 != expr_stack) + { + ieee_error (abfd, bytes, expr_start, "expression stack mismatch"); + return false; + } + + *pv = *--esp; + + return true; +} + +/* Return an IEEE builtin type. */ + +static debug_type +ieee_builtin_type (dhandle, abfd, types, bytes, p, indx) + PTR dhandle; + bfd *abfd; + struct ieee_types *types; + const bfd_byte *bytes; + const bfd_byte *p; + unsigned int indx; +{ + boolean ptr; + debug_type type; + const char *name; + + if (indx < BUILTIN_TYPE_COUNT + && types->builtins[indx] != DEBUG_TYPE_NULL) + return types->builtins[indx]; + + ptr = false; + switch (indx) + { + default: + ieee_error (abfd, bytes, p, "unknown builtin type"); + return NULL; + + case 32: + ptr = true; + /* Fall through. */ + case 0: + type = debug_make_void_type (dhandle); + name = NULL; + break; + + case 33: + ptr = true; + /* Fall through. */ + case 1: + type = debug_make_void_type (dhandle); + name = "void"; + break; + + case 34: + ptr = true; + /* Fall through. */ + case 2: + type = debug_make_int_type (dhandle, 1, false); + name = "signed char"; + break; + + case 35: + ptr = true; + /* Fall through. */ + case 3: + type = debug_make_int_type (dhandle, 1, true); + name = "unsigned char"; + break; + + case 36: + ptr = true; + /* Fall through. */ + case 4: + type = debug_make_int_type (dhandle, 2, false); + name = "signed short int"; + break; + + case 37: + ptr = true; + /* Fall through. */ + case 5: + type = debug_make_int_type (dhandle, 2, true); + name = "unsigned short int"; + break; + + case 38: + ptr = true; + /* Fall through. */ + case 6: + type = debug_make_int_type (dhandle, 4, false); + name = "signed long"; + break; + + case 39: + ptr = true; + /* Fall through. */ + case 7: + type = debug_make_int_type (dhandle, 4, true); + name = "unsigned long"; + break; + + case 40: + ptr = true; + /* Fall through. */ + case 8: + type = debug_make_int_type (dhandle, 8, false); + name = "signed long long"; + break; + + case 41: + ptr = true; + /* Fall through. */ + case 9: + type = debug_make_int_type (dhandle, 8, true); + name = "unsigned long long"; + break; + + case 42: + ptr = true; + /* Fall through. */ + case 10: + type = debug_make_float_type (dhandle, 4); + name = "float"; + break; + + case 43: + ptr = true; + /* Fall through. */ + case 11: + type = debug_make_float_type (dhandle, 8); + name = "double"; + break; + + case 44: + ptr = true; + /* Fall through. */ + case 12: + /* FIXME: The size for this type should depend upon the + processor. */ + type = debug_make_float_type (dhandle, 12); + name = "long double"; + break; + + case 45: + ptr = true; + /* Fall through. */ + case 13: + type = debug_make_float_type (dhandle, 16); + name = "long long double"; + break; + + case 46: + ptr = true; + /* Fall through. */ + case 14: + type = debug_make_array_type (dhandle, + ieee_builtin_type (dhandle, abfd, types, + bytes, p, 19), + ieee_builtin_type (dhandle, abfd, types, + bytes, p, 16), + 0, -1, true); + name = "QUOTED STRING"; + break; + + case 47: + ptr = true; + /* Fall through. */ + case 15: + /* FIXME: This should be a code address. */ + type = debug_make_int_type (dhandle, 4, true); + name = "instruction address"; + break; + + case 48: + ptr = true; + /* Fall through. */ + case 16: + /* FIXME: The size for this type should depend upon the + processor. */ + type = debug_make_int_type (dhandle, 4, false); + name = "int"; + break; + + case 49: + ptr = true; + /* Fall through. */ + case 17: + /* FIXME: The size for this type should depend upon the + processor. */ + type = debug_make_int_type (dhandle, 4, true); + name = "unsigned"; + break; + + case 50: + ptr = true; + /* Fall through. */ + case 18: + /* FIXME: The size for this type should depend upon the + processor. */ + type = debug_make_int_type (dhandle, 4, true); + name = "unsigned int"; + break; + + case 51: + ptr = true; + /* Fall through. */ + case 19: + type = debug_make_int_type (dhandle, 1, false); + name = "char"; + break; + + case 52: + ptr = true; + /* Fall through. */ + case 20: + type = debug_make_int_type (dhandle, 4, false); + name = "long"; + break; + + case 53: + ptr = true; + /* Fall through. */ + case 21: + type = debug_make_int_type (dhandle, 2, false); + name = "short"; + break; + + case 54: + ptr = true; + /* Fall through. */ + case 22: + type = debug_make_int_type (dhandle, 2, true); + name = "unsigned short"; + break; + + case 55: + ptr = true; + /* Fall through. */ + case 23: + type = debug_make_int_type (dhandle, 2, false); + name = "short int"; + break; + + case 56: + ptr = true; + /* Fall through. */ + case 24: + type = debug_make_int_type (dhandle, 2, false); + name = "signed short"; + break; + + case 57: + ptr = true; + /* Fall through. */ + case 25: + ieee_error (abfd, bytes, p, "BCD float type not supported"); + return false; + } + + if (ptr) + type = debug_make_pointer_type (dhandle, type); + else if (name != NULL) + type = debug_name_type (dhandle, name, type); + + assert (indx < BUILTIN_TYPE_COUNT); + + types->builtins[indx] = type; + + return type; +} + +/* Read a type index and return the corresponding type. */ + +static boolean +ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, ptype) + PTR dhandle; + bfd *abfd; + struct ieee_types *types; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; + debug_type *ptype; +{ + const bfd_byte *start; + bfd_vma indx; + + start = *pp; + + if (! ieee_read_number (abfd, bytes, pp, pend, &indx)) + return false; + + if (indx < 256) + { + *ptype = ieee_builtin_type (dhandle, abfd, types, bytes, start, indx); + if (*ptype == NULL) + return false; + return true; + } + + indx -= 256; + if (indx >= types->alloc + || types->types[indx].type == DEBUG_TYPE_NULL) + { + ieee_error (abfd, bytes, start, "undefined type"); + return false; + } + + *ptype = types->types[indx].type; + + return true; +} + +/* Convert a register number in IEEE debugging information into a + generic register number. */ + +static int +ieee_regno_to_gen (abfd, r) + bfd *abfd; + int r; +{ + return r; +} + +/* 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_blockstack blockstack; + struct ieee_vars vars; + struct ieee_types types; + unsigned int i; + const bfd_byte *p, *pend; + + blockstack.bsp = blockstack.stack; + vars.alloc = 0; + vars.vars = NULL; + types.alloc = 0; + types.types = NULL; + for (i = 0; i < BUILTIN_TYPE_COUNT; i++) + types.builtins[i] = DEBUG_TYPE_NULL; + + p = bytes; + pend = bytes + len; + 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 (abfd, bytes, record_start, "unexpected number"); + return false; + } + + switch (c) + { + default: + ieee_error (abfd, bytes, record_start, "unexpected record type"); + return false; + + case ieee_bb_record_enum: + if (! parse_ieee_bb (dhandle, abfd, &types, &blockstack, bytes, + &p, pend)) + return false; + break; + + case ieee_be_record_enum: + if (! parse_ieee_be (dhandle, abfd, &blockstack, bytes, &p, pend)) + return false; + break; + + case ieee_nn_record: + if (! parse_ieee_nn (dhandle, abfd, &vars, bytes, &p, pend)) + return false; + break; + + case ieee_ty_record_enum: + if (! parse_ieee_ty (dhandle, abfd, &types, &vars, bytes, &p, pend)) + return false; + break; + + case ieee_atn_record_enum: + if (! parse_ieee_atn (dhandle, abfd, &types, &vars, + (blockstack.bsp <= blockstack.stack + ? 0 + : blockstack.bsp[-1].kind), + bytes, &p, pend)) + return false; + break; + } + } + + if (blockstack.bsp != blockstack.stack) + { + ieee_error (abfd, (const bfd_byte *) NULL, (const bfd_byte *) NULL, + "blocks left on stack at end"); + return false; + } + + return true; +} + +/* Handle an IEEE BB record. */ + +static boolean +parse_ieee_bb (dhandle, abfd, types, blockstack, bytes, pp, pend) + PTR dhandle; + bfd *abfd; + struct ieee_types *types; + struct ieee_blockstack *blockstack; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; +{ + const bfd_byte *block_start; + bfd_byte b; + bfd_vma size; + const char *name; + unsigned long namlen; + char *namcopy; + + block_start = *pp; + + b = **pp; + ++*pp; + + if (! ieee_read_number (abfd, bytes, pp, pend, &size) + || ! ieee_read_id (abfd, bytes, pp, pend, &name, &namlen)) + return 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 (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 (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 (abfd, bytes, pp, pend, &stackspace) + || ! ieee_read_number (abfd, bytes, pp, pend, &typindx) + || ! ieee_read_expression (abfd, bytes, pp, pend, &offset)) + return false; + + /* We have no way to record the stack space. FIXME. */ + + if (typindx < 256) + { + return_type = ieee_builtin_type (dhandle, abfd, types, bytes, + block_start, typindx); + if (return_type == NULL) + return false; + } + else + { + typindx -= 256; + if (typindx >= types->alloc + || types->types[typindx].type == DEBUG_TYPE_NULL) + { + ieee_error (abfd, bytes, block_start, "undefined type index"); + return false; + } + return_type = types->types[typindx].return_type; + if (return_type == NULL) + return_type = types->types[typindx].type; + } + + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_record_function (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 (abfd, bytes, pp, pend, &ignore, + &present)) + return false; + if (! present) + break; + } + + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_start_source (dhandle, namcopy)) + return false; + } + break; + + case 6: + /* BB6: Local function or block. */ + { + bfd_vma stackspace, typindx, offset; + + if (! ieee_read_number (abfd, bytes, pp, pend, &stackspace) + || ! ieee_read_number (abfd, bytes, pp, pend, &typindx) + || ! ieee_read_expression (abfd, bytes, pp, pend, &offset)) + return false; + + /* We have no way to record the stack space. FIXME. */ + + if (namlen == 0) + { + if (! debug_start_block (dhandle, offset)) + return false; + /* Change b to indicate that this is a block + rather than a function. */ + b = 0x86; + } + else + { + debug_type return_type; + + if (typindx < 256) + { + return_type = ieee_builtin_type (dhandle, abfd, types, bytes, + block_start, typindx); + if (return_type == NULL) + return false; + } + else + { + typindx -= 256; + if (typindx >= types->alloc + || types->types[typindx].type == DEBUG_TYPE_NULL) + { + ieee_error (abfd, bytes, block_start, + "undefined type index"); + return false; + } + return_type = types->types[typindx].return_type; + if (return_type == NULL) + return_type = types->types[typindx].type; + } + + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_record_function (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 (abfd, bytes, pp, pend, &inam, &inamlen) + || ! ieee_read_number (abfd, bytes, pp, pend, &tool_type) + || ! ieee_read_optional_id (abfd, bytes, pp, pend, &vstr, &vstrlen, + &present)) + return false; + for (i = 0; i < 6; i++) + { + bfd_vma ignore; + + if (! ieee_read_optional_number (abfd, bytes, pp, pend, &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 (abfd, bytes, pp, pend, §ype) + || ! ieee_read_number (abfd, bytes, pp, pend, &secindx) + || ! ieee_read_expression (abfd, bytes, pp, pend, &offset) + || ! ieee_read_optional_number (abfd, bytes, pp, pend, &map, + &present)) + return false; + } + break; + + default: + ieee_error (abfd, bytes, block_start, "unknown BB type"); + return false; + } + + + /* Push this block on the block stack. */ + + if (blockstack->bsp >= blockstack->stack + BLOCKSTACK_SIZE) + { + ieee_error (abfd, (const bfd_byte *) NULL, (const bfd_byte *) NULL, + "stack overflow"); + return false; + } + + blockstack->bsp->kind = b; + if (b == 5) + blockstack->bsp->filename = namcopy; + ++blockstack->bsp; + + return true; +} + +/* Handle an IEEE BE record. */ + +static boolean +parse_ieee_be (dhandle, abfd, blockstack, bytes, pp, pend) + PTR dhandle; + bfd *abfd; + struct ieee_blockstack *blockstack; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; +{ + bfd_vma offset; + + if (blockstack->bsp <= blockstack->stack) + { + ieee_error (abfd, bytes, *pp, "stack underflow"); + return false; + } + --blockstack->bsp; + + switch (blockstack->bsp->kind) + { + case 4: + case 6: + if (! ieee_read_expression (abfd, bytes, pp, pend, &offset)) + return false; + if (! debug_end_function (dhandle, offset)) + return false; + break; + + case 0x86: + /* This is BE6 when BB6 started a block rather than a local + function. */ + if (! ieee_read_expression (abfd, bytes, pp, pend, &offset)) + return false; + if (! debug_end_block (dhandle, offset)) + 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 (blockstack->bsp > blockstack->stack) + { + struct ieee_block *bl; + + bl = blockstack->bsp; + do + { + --bl; + if (bl->kind == 5) + { + if (! debug_start_source (dhandle, bl->filename)) + return false; + break; + } + } + while (bl != blockstack->stack); + } + break; + + case 11: + if (! ieee_read_expression (abfd, bytes, pp, pend, &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 (dhandle, abfd, vars, bytes, pp, pend) + PTR dhandle; + bfd *abfd; + struct ieee_vars *vars; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; +{ + const bfd_byte *nn_start; + bfd_vma varindx; + const char *name; + unsigned long namlen; + + nn_start = *pp; + + if (! ieee_read_number (abfd, bytes, pp, pend, &varindx) + || ! ieee_read_id (abfd, bytes, pp, pend, &name, &namlen)) + return false; + + if (varindx < 32) + { + ieee_error (abfd, bytes, nn_start, "illegal variable index"); + return false; + } + varindx -= 32; + + if (varindx >= vars->alloc) + { + unsigned int alloc; + + alloc = vars->alloc; + if (alloc == 0) + alloc = 4; + while (varindx >= alloc) + alloc *= 2; + vars->vars = ((struct ieee_var *) + xrealloc (vars->vars, alloc * sizeof *vars->vars)); + memset (vars->vars + vars->alloc, 0, + (alloc - vars->alloc) * sizeof *vars->vars); + vars->alloc = alloc; + } + + vars->vars[varindx].name = name; + vars->vars[varindx].namlen = namlen; + + return true; +} + +/* Parse a TY record. */ + +static boolean +parse_ieee_ty (dhandle, abfd, types, vars, bytes, pp, pend) + PTR dhandle; + bfd *abfd; + struct ieee_types *types; + struct ieee_vars *vars; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; +{ + const bfd_byte *ty_start, *ty_var_start, *ty_code_start; + bfd_vma typeindx, varindx, tc; + debug_type type; + boolean tag, typdef; + unsigned long type_bitsize; + debug_type return_type; + + ty_start = *pp; + + if (! ieee_read_number (abfd, bytes, pp, pend, &typeindx)) + return false; + + if (typeindx < 256) + { + ieee_error (abfd, bytes, ty_start, "illegal type index"); + return false; + } + typeindx -= 256; + + if (typeindx >= types->alloc) + { + unsigned int nalloc; + struct ieee_type *t, *tend; + + nalloc = types->alloc; + if (nalloc == 0) + nalloc = 4; + while (typeindx >= nalloc) + nalloc *= 2; + types->types = ((struct ieee_type *) + xrealloc (types->types, nalloc * sizeof *types->types)); + tend = types->types + nalloc; + for (t = types->types + types->alloc; t < tend; t++) + { + t->bitsize = 0; + t->type = DEBUG_TYPE_NULL; + } + types->alloc = nalloc; + } + + if (**pp != 0xce) + { + ieee_error (abfd, bytes, *pp, "unknown TY code"); + return false; + } + ++*pp; + + ty_var_start = *pp; + + if (! ieee_read_number (abfd, bytes, pp, pend, &varindx)) + return false; + + if (varindx < 32) + { + ieee_error (abfd, bytes, ty_var_start, "illegal variable index"); + return false; + } + varindx -= 32; + + if (varindx >= vars->alloc || vars->vars[varindx].name == NULL) + { + ieee_error (abfd, bytes, ty_var_start, "undefined variable in TY"); + return false; + } + + ty_code_start = *pp; + + if (! ieee_read_number (abfd, bytes, pp, pend, &tc)) + return false; + + tag = false; + typdef = false; + type_bitsize = 0; + return_type = DEBUG_TYPE_NULL; + switch (tc) + { + default: + ieee_error (abfd, bytes, 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 (abfd, bytes, pp, pend, &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 (dhandle, abfd, types, bytes, pp, pend, + &ele_type) + || ! ieee_read_number (abfd, bytes, pp, pend, &lower) + || ! ieee_read_number (abfd, bytes, pp, pend, &upper)) + return false; + type = debug_make_array_type (dhandle, ele_type, + debug_make_int_type (dhandle, 4, false), + (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 (abfd, bytes, pp, pend, &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 (abfd, bytes, pp, pend, &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 (abfd, bytes, pp, pend, &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 (abfd, bytes, pp, pend, &name, + &namlen, &present)) + return false; + if (! present) + break; + if (! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, + &ftype) + || ! ieee_read_number (abfd, bytes, pp, pend, &bitpos) + || ! ieee_read_number (abfd, bytes, pp, pend, &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 (abfd, bytes, pp, pend, &name, + &namlen, &present)) + return false; + if (! present) + break; + if (! ieee_read_number (abfd, bytes, pp, pend, &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 (dhandle, abfd, types, bytes, pp, pend, &t)) + return false; + type = debug_make_pointer_type (dhandle, t); + } + break; + + case 'R': + /* Range. */ + { + bfd_vma low, high, signedp, size; + + if (! ieee_read_number (abfd, bytes, pp, pend, &low) + || ! ieee_read_number (abfd, bytes, pp, pend, &high) + || ! ieee_read_number (abfd, bytes, pp, pend, &signedp) + || ! ieee_read_number (abfd, bytes, pp, pend, &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 (abfd, bytes, pp, pend, &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 (abfd, bytes, pp, pend, &name, + &namlen, &present)) + return false; + if (! present) + break; + if (! ieee_read_number (abfd, bytes, pp, pend, &tindx) + || ! ieee_read_number (abfd, bytes, pp, pend, &offset)) + return false; + + if (tindx < 256) + { + ftype = ieee_builtin_type (dhandle, abfd, types, bytes, + ty_code_start, tindx); + bitsize = 0; + offset *= 8; + } + else + { + struct ieee_type *t; + + tindx -= 256; + if (tindx >= types->alloc + || types->types[tindx].type == DEBUG_TYPE_NULL) + { + ieee_error (abfd, bytes, ty_start, "undefined type index"); + return false; + } + t = &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 (dhandle, abfd, types, bytes, pp, pend, + &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; + + /* FIXME: We ignore the attribute and the argument names. */ + + if (! ieee_read_number (abfd, bytes, pp, pend, &attr) + || ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, + &rtype) + || ! ieee_read_number (abfd, bytes, pp, pend, &nargs)) + return false; + do + { + const char *name; + unsigned long namlen; + + if (! ieee_read_optional_id (abfd, bytes, pp, pend, &name, + &namlen, &present)) + return false; + } + while (present); + + type = debug_make_function_type (dhandle, rtype); + return_type = rtype; + } + break; + + case 'Z': + /* Array with 0 lower bound. */ + { + debug_type etype; + bfd_vma high; + + if (! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, + &etype) + || ! ieee_read_number (abfd, bytes, pp, pend, &high)) + return false; + + type = debug_make_array_type (dhandle, etype, + debug_make_int_type (dhandle, 4, false), + 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 (abfd, bytes, pp, pend, &name, &namlen)) + return false; + + type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8); + } + break; + + case 'f': + /* Pascal file name. FIXME. */ + ieee_error (abfd, bytes, ty_code_start, + "Pascal file name not supported"); + return false; + + case 'g': + /* Bitfield type. */ + { + bfd_vma signedp, bitsize; + + if (! ieee_read_number (abfd, bytes, pp, pend, &signedp) + || ! ieee_read_number (abfd, bytes, pp, pend, &bitsize) + || ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, + &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 (abfd, bytes, pp, pend, &kind) + || ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, + &t)) + return false; + + switch (kind) + { + default: + ieee_error (abfd, bytes, 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 (abfd, bytes, pp, pend, &size) + || ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, + &etype)) + return false; + + /* FIXME: We ignore the size. */ + + type = debug_make_set_type (dhandle, etype, false); + } + break; + + case 'x': + /* Procedure with compiler dependencies. FIXME: This is an + extern declaration, which we have no way of representing. */ + { + bfd_vma attr, frame_type, push_mask, nargs, level, father; + debug_type rtype; + boolean present; + + /* FIXME: We ignore almost all this information. */ + + if (! ieee_read_number (abfd, bytes, pp, pend, &attr) + || ! ieee_read_number (abfd, bytes, pp, pend, &frame_type) + || ! ieee_read_number (abfd, bytes, pp, pend, &push_mask) + || ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, + &rtype) + || ! ieee_read_number (abfd, bytes, pp, pend, &nargs)) + return false; + if (nargs != (bfd_vma) -1) + { + for (; nargs > 0; nargs--) + { + debug_type atype; + + if (! ieee_read_type_index (dhandle, abfd, types, bytes, pp, + pend, &atype)) + return false; + } + } + if (! ieee_read_number (abfd, bytes, pp, pend, &level) + || ! ieee_read_optional_number (abfd, bytes, pp, pend, &father, + &present)) + return false; + + type = debug_make_function_type (dhandle, rtype); + return_type = rtype; + } + break; + } + + /* Record the type in the table. If the corresponding NN record has + a name, name it. FIXME: Is this always correct? */ + + if (type == NULL) + return false; + + if ((tag || typdef) + && vars->vars[varindx].namlen > 0) + { + const char *name; + + name = savestring (vars->vars[varindx].name, + vars->vars[varindx].namlen); + if (tag) + type = debug_tag_type (dhandle, name, type); + else + type = debug_name_type (dhandle, name, type); + if (type == NULL) + return false; + } + + types->types[typeindx].type = type; + types->types[typeindx].bitsize = type_bitsize; + types->types[typeindx].return_type = return_type; + + return true; +} + +/* Parse an ATN record. */ + +static boolean +parse_ieee_atn (dhandle, abfd, types, vars, blocktype, bytes, pp, pend) + PTR dhandle; + bfd *abfd; + struct ieee_types *types; + struct ieee_vars *vars; + int blocktype; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; +{ + const bfd_byte *atn_start, *atn_code_start; + bfd_vma varindx; + boolean zeroindx; + debug_type type; + bfd_vma atn_code; + bfd_vma v, v2, v3, v4, v5; + const char *name; + unsigned long namlen; + char *namcopy; + boolean present; + + atn_start = *pp; + + if (! ieee_read_number (abfd, bytes, pp, pend, &varindx) + || ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, &type)) + return false; + + atn_code_start = *pp; + + if (! ieee_read_number (abfd, bytes, pp, pend, &atn_code)) + return false; + + if (varindx == 0) + { + zeroindx = true; + name = ""; + namlen = 0; + } + else if (varindx < 32) + { + ieee_error (abfd, bytes, atn_start, "illegal variable index"); + return false; + } + else + { + varindx -= 32; + zeroindx = false; + if (varindx >= vars->alloc || vars->vars[varindx].name == NULL) + { + ieee_error (abfd, bytes, atn_start, "undefined variable in ATN"); + return false; + } + + vars->vars[varindx].type = type; + + name = vars->vars[varindx].name; + namlen = vars->vars[varindx].namlen; + } + + switch (atn_code) + { + default: + ieee_error (abfd, bytes, atn_code_start, "unknown ATN type"); + return false; + + case 1: + /* Automatic variable. */ + if (! ieee_read_number (abfd, bytes, pp, pend, &v)) + return false; + namcopy = savestring (name, namlen); + if (type == NULL) + type = debug_make_void_type (dhandle); + return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v); + + case 2: + /* Register variable. */ + if (! ieee_read_number (abfd, bytes, pp, pend, &v)) + return false; + namcopy = savestring (name, namlen); + if (type == NULL) + type = debug_make_void_type (dhandle); + return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, + ieee_regno_to_gen (abfd, v)); + + case 3: + /* Static variable. */ + if (! ieee_require_asn (abfd, bytes, pp, pend, &v)) + return false; + namcopy = savestring (name, namlen); + if (type == NULL) + type = debug_make_void_type (dhandle); + 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. */ + return true; + + case 5: + /* External variable. We don't currently record these. FIXME. */ + return true; + + case 7: + if (! ieee_read_number (abfd, bytes, pp, pend, &v) + || ! ieee_read_number (abfd, bytes, pp, pend, &v2) + || ! ieee_read_optional_number (abfd, bytes, pp, pend, &v3, + &present)) + return false; + if (present) + { + if (! ieee_read_optional_number (abfd, bytes, pp, pend, &v4, + &present)) + return false; + } + + /* We just ignore the two optional fields in v3 and v4, since + they are not defined. */ + + if (! ieee_require_asn (abfd, bytes, pp, pend, &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 (abfd, bytes, pp, pend, &v)) + return false; + namcopy = savestring (name, namlen); + if (type == NULL) + type = debug_make_void_type (dhandle); + return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v); + + case 9: + /* Variable lifetime information. */ + if (! ieee_read_number (abfd, bytes, pp, pend, &v)) + return false; + + /* We have no way to record this information. FIXME. */ + return true; + + case 10: + /* Locked register. */ + if (! ieee_read_number (abfd, bytes, pp, pend, &v) + || ! ieee_read_number (abfd, bytes, pp, pend, &v2)) + return false; + + /* I don't know what this means. FIXME. */ + + ieee_error (abfd, bytes, atn_code_start, "unsupported ATN10"); + + /* Return true to keep going. */ + return true; + + case 11: + /* Reserved for FORTRAN common. */ + ieee_error (abfd, bytes, 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 (abfd, bytes, pp, pend, &v) + || ! ieee_read_number (abfd, bytes, pp, pend, &v2) + || ! ieee_read_optional_number (abfd, bytes, pp, pend, &v3, + &present)) + return false; + if (present) + { + if (! ieee_read_optional_number (abfd, bytes, pp, pend, &v4, + &present)) + return false; + if (present) + { + if (! ieee_read_optional_number (abfd, bytes, pp, pend, &v5, + &present)) + return false; + } + } + + /* We have no way to record this information. FIXME. */ + + ieee_error (abfd, bytes, 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. */ + ieee_error (abfd, bytes, atn_code_start, "unsupported ATN16"); + return false; + + case 19: + /* Static variable from assembler. */ + v2 = 0; + if (! ieee_read_number (abfd, bytes, pp, pend, &v) + || ! ieee_read_optional_number (abfd, bytes, pp, pend, &v2, + &present) + || ! ieee_require_asn (abfd, bytes, pp, pend, &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 (abfd, bytes, pp, pend, &v) + || ! ieee_read_number (abfd, bytes, pp, pend, &v2) + || ! ieee_read_optional_id (abfd, bytes, pp, pend, &name, &namlen, + &present)) + return false; + + /* We just ignore all of this stuff. FIXME. */ + + for (; v2 > 0; --v2) + { + ieee_record_enum_type c; + bfd_vma vindx; + const char *str; + unsigned long strlen; + + c = (ieee_record_enum_type) **pp; + ++*pp; + if (c != ieee_at_record_enum + && c != ieee_e2_first_byte_enum) + { + ieee_error (abfd, bytes, *pp - 1, "bad misc record"); + return false; + } + + c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp); + ++*pp; + switch (c) + { + default: + ieee_error (abfd, bytes, *pp - 2, "bad misc record"); + return false; + + case ieee_atn_record_enum: + if (! ieee_read_number (abfd, bytes, pp, pend, &vindx)) + return false; + if ((*pp)[0] != 0 || (*pp)[1] != 65) + { + ieee_error (abfd, bytes, *pp, "bad atn in misc"); + return false; + } + *pp += 2; + if (! ieee_read_id (abfd, bytes, pp, pend, &str, &strlen)) + return false; + break; + + case ieee_asn_record_enum: + if (! ieee_read_number (abfd, bytes, pp, pend, &vindx) + || ! ieee_read_expression (abfd, bytes, pp, pend, &v3)) + return false; + break; + } + } + + return true; + } + + /*NOTREACHED*/ +} + +/* Require an ASN record. */ + +static boolean +ieee_require_asn (abfd, bytes, pp, pend, pv) + bfd *abfd; + const bfd_byte *bytes; + const bfd_byte **pp; + const bfd_byte *pend; + 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 (abfd, bytes, 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 (abfd, bytes, start, "missing required ASN"); + return false; + } + ++*pp; + + /* Just ignore the variable index. */ + if (! ieee_read_number (abfd, bytes, pp, pend, &varindx)) + return false; + + return ieee_read_expression (abfd, bytes, pp, pend, pv); +} |