From: Ian Lance Taylor Date: Tue, 16 Apr 1996 17:53:58 +0000 (+0000) Subject: * rdcoff.c: New file. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f32fb3fd1fb24d8d72ba1abe43ec8cfd0cf4a89d;p=binutils-gdb.git * rdcoff.c: New file. * rddbg.c (read_debugging_info): Read COFF symbols if COFF flavour and no stabs were found. * budbg.h (parse_coff): Declare. * Makefile.in: Rebuild dependencies. (CFILES): Add rdcoff.c. (DEBUG_OBJS): Add rdcoff.o. --- diff --git a/binutils/.Sanitize b/binutils/.Sanitize index aaf5e0118ad..bd1a78f7c5c 100644 --- a/binutils/.Sanitize +++ b/binutils/.Sanitize @@ -78,6 +78,7 @@ objdump.c prdbg.c ranlib.1 ranlib.sh +rdcoff.c rddbg.c sanity.sh size.1 diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 113e77e3108..13094521daf 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,13 @@ +Tue Apr 16 13:50:22 1996 Ian Lance Taylor + + * rdcoff.c: New file. + * rddbg.c (read_debugging_info): Read COFF symbols if COFF flavour + and no stabs were found. + * budbg.h (parse_coff): Declare. + * Makefile.in: Rebuild dependencies. + (CFILES): Add rdcoff.c. + (DEBUG_OBJS): Add rdcoff.o. + Mon Apr 15 15:55:01 1996 Doug Evans * nlmconv.c (choose_temp_base{,_try}): Delete, in libiberty now. diff --git a/binutils/Makefile.in b/binutils/Makefile.in index c875c9ab401..2c25944a414 100644 --- a/binutils/Makefile.in +++ b/binutils/Makefile.in @@ -136,8 +136,8 @@ 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 + objcopy.c objdump.c prdbg.c rdcoff.c rddbg.c size.c srconv.c \ + stabs.c strings.c sysdump.c version.c wrstabs.c GENERATED_CFILES = \ underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \ @@ -146,7 +146,8 @@ GENERATED_CFILES = \ .c.o: $(CC) -c $(ALL_CFLAGS) $< -DEBUG_OBJS = rddbg.o debug.o stabs.o ieee.o +DEBUG_OBJS = rddbg.o debug.o stabs.o ieee.o rdcoff.o +WRITE_DEBUG_OBJS = $(DEBUG_OBJS) wrstabs.o LIBIBERTY = ../libiberty/libiberty.a @@ -248,20 +249,23 @@ dvi: binutils.dvi $(SIZE_PROG): $(ADDL_DEPS) size.o $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(SIZE_PROG) size.o $(ADDL_LIBS) $(EXTRALIBS) -$(OBJCOPY_PROG): $(ADDL_DEPS) objcopy.o not-strip.o $(DEBUG_OBJS) - $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(OBJCOPY_PROG) objcopy.o not-strip.o $(DEBUG_OBJS) $(ADDL_LIBS) $(EXTRALIBS) +$(OBJCOPY_PROG): $(ADDL_DEPS) objcopy.o not-strip.o $(WRITE_DEBUG_OBJS) + $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(OBJCOPY_PROG) objcopy.o not-strip.o $(WRITE_DEBUG_OBJS) $(ADDL_LIBS) $(EXTRALIBS) $(STRINGS_PROG): $(ADDL_DEPS) strings.o $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(STRINGS_PROG) strings.o $(ADDL_LIBS) $(EXTRALIBS) -$(STRIP_PROG): $(ADDL_DEPS) objcopy.o is-strip.o $(DEBUG_OBJS) - $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(STRIP_PROG) objcopy.o is-strip.o $(DEBUG_OBJS) $(ADDL_LIBS) $(EXTRALIBS) +$(STRIP_PROG): $(ADDL_DEPS) objcopy.o is-strip.o $(WRITE_DEBUG_OBJS) + $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(STRIP_PROG) objcopy.o is-strip.o $(WRITE_DEBUG_OBJS) $(ADDL_LIBS) $(EXTRALIBS) $(NM_PROG): $(ADDL_DEPS) nm.o $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(NM_PROG) nm.o $(ADDL_LIBS) $(EXTRALIBS) +#libbfd is searched twice here ($(BFDLIB) and $(ADDL_LIBS)) because when a +#shared libbfd is built with --enable-commonbfdlib, all of libopcodes is +#available in libbfd.so and we don't want to link anything from libopcodes.a $(OBJDUMP_PROG): $(ADDL_DEPS) objdump.o prdbg.o $(DEBUG_OBJS) $(OPCODES_DEP) - $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(OBJDUMP_PROG) objdump.o prdbg.o $(DEBUG_OBJS) $(OPCODES) $(ADDL_LIBS) $(EXTRALIBS) + $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(OBJDUMP_PROG) objdump.o prdbg.o $(DEBUG_OBJS) $(BFDLIB) $(OPCODES) $(ADDL_LIBS) $(EXTRALIBS) underscore.c: stamp-under ; @true @@ -694,11 +698,15 @@ objcopy.o: objcopy.c ../bfd/bfd.h $(INCDIR)/ansidecl.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 + $(INCDIR)/libiberty.h debug.h budbg.h $(INCDIR)/aout/aout64.h 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 +rdcoff.o: rdcoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/obstack.h $(INCDIR)/coff/internal.h bucomm.h \ + config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + $(INCDIR)/demangle.h debug.h budbg.h ../bfd/libcoff.h \ + $(INCDIR)/bfdlink.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 @@ -710,8 +718,9 @@ srconv.o: srconv.c bucomm.h config.h $(INCDIR)/fopen-same.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 + $(INCDIR)/libiberty.h $(INCDIR)/demangle.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 @@ -719,6 +728,10 @@ 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 +wrstabs.o: wrstabs.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 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 \ diff --git a/binutils/rdcoff.c b/binutils/rdcoff.c new file mode 100644 index 00000000000..9f7660b278e --- /dev/null +++ b/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 . + + 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/binutils/rddbg.c b/binutils/rddbg.c index d42d04863ed..b2602af4c6e 100644 --- a/binutils/rddbg.c +++ b/binutils/rddbg.c @@ -54,8 +54,6 @@ read_debugging_info (abfd, syms, symcount) if (dhandle == NULL) return NULL; - /* All we know about right now is stabs. */ - if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle, &found)) return NULL; @@ -73,6 +71,17 @@ read_debugging_info (abfd, syms, symcount) 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",