133965Sjdp/* stabs.c -- Parse COFF debugging information 2218822Sdim Copyright 1996, 1999, 2000, 2002, 2003, 2007 3218822Sdim Free Software Foundation, Inc. 433965Sjdp Written by Ian Lance Taylor <ian@cygnus.com>. 533965Sjdp 633965Sjdp This file is part of GNU Binutils. 733965Sjdp 833965Sjdp This program is free software; you can redistribute it and/or modify 933965Sjdp it under the terms of the GNU General Public License as published by 1033965Sjdp the Free Software Foundation; either version 2 of the License, or 1133965Sjdp (at your option) any later version. 1233965Sjdp 1333965Sjdp This program is distributed in the hope that it will be useful, 1433965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1533965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965Sjdp GNU General Public License for more details. 1733965Sjdp 1833965Sjdp You should have received a copy of the GNU General Public License 1933965Sjdp along with this program; if not, write to the Free Software 20218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 21218822Sdim 02110-1301, USA. */ 2233965Sjdp 2333965Sjdp/* This file contains code which parses COFF debugging information. */ 2433965Sjdp 25218822Sdim#include "sysdep.h" 2633965Sjdp#include "bfd.h" 2733965Sjdp#include "coff/internal.h" 28218822Sdim#include "libiberty.h" 2933965Sjdp#include "bucomm.h" 3033965Sjdp#include "debug.h" 3133965Sjdp#include "budbg.h" 3233965Sjdp 3333965Sjdp/* FIXME: We should not need this BFD internal file. We need it for 3433965Sjdp the N_BTMASK, etc., values. */ 3533965Sjdp#include "libcoff.h" 3633965Sjdp 3733965Sjdp/* These macros extract the right mask and shifts for this BFD. They 3833965Sjdp assume that there is a local variable named ABFD. This is so that 3933965Sjdp macros like ISFCN and DECREF, from coff/internal.h, will work 4033965Sjdp without modification. */ 4133965Sjdp#define N_BTMASK (coff_data (abfd)->local_n_btmask) 4233965Sjdp#define N_BTSHFT (coff_data (abfd)->local_n_btshft) 4333965Sjdp#define N_TMASK (coff_data (abfd)->local_n_tmask) 4433965Sjdp#define N_TSHIFT (coff_data (abfd)->local_n_tshift) 4533965Sjdp 4633965Sjdp/* This structure is used to hold the symbols, as well as the current 4733965Sjdp location within the symbols. */ 4833965Sjdp 4933965Sjdpstruct coff_symbols 5033965Sjdp{ 5133965Sjdp /* The symbols. */ 5233965Sjdp asymbol **syms; 5333965Sjdp /* The number of symbols. */ 5433965Sjdp long symcount; 5533965Sjdp /* The index of the current symbol. */ 5633965Sjdp long symno; 5733965Sjdp /* The index of the current symbol in the COFF symbol table (where 5833965Sjdp each auxent counts as a symbol). */ 5933965Sjdp long coff_symno; 6033965Sjdp}; 6133965Sjdp 6233965Sjdp/* The largest basic type we are prepared to handle. */ 6333965Sjdp 6433965Sjdp#define T_MAX (T_LNGDBL) 6533965Sjdp 6633965Sjdp/* This structure is used to hold slots. */ 6733965Sjdp 6833965Sjdpstruct coff_slots 6933965Sjdp{ 7033965Sjdp /* Next set of slots. */ 7133965Sjdp struct coff_slots *next; 7233965Sjdp /* Slots. */ 7333965Sjdp#define COFF_SLOTS (16) 7433965Sjdp debug_type slots[COFF_SLOTS]; 7533965Sjdp}; 7633965Sjdp 7733965Sjdp/* This structure is used to map symbol indices to types. */ 7833965Sjdp 7933965Sjdpstruct coff_types 8033965Sjdp{ 8133965Sjdp /* Slots. */ 8233965Sjdp struct coff_slots *slots; 8333965Sjdp /* Basic types. */ 8433965Sjdp debug_type basic[T_MAX + 1]; 8533965Sjdp}; 8633965Sjdp 87130561Sobrienstatic debug_type *coff_get_slot (struct coff_types *, int); 8833965Sjdpstatic debug_type parse_coff_type 89130561Sobrien (bfd *, struct coff_symbols *, struct coff_types *, long, int, 90130561Sobrien union internal_auxent *, bfd_boolean, void *); 9133965Sjdpstatic debug_type parse_coff_base_type 92130561Sobrien (bfd *, struct coff_symbols *, struct coff_types *, long, int, 93130561Sobrien union internal_auxent *, void *); 9433965Sjdpstatic debug_type parse_coff_struct_type 95130561Sobrien (bfd *, struct coff_symbols *, struct coff_types *, int, 96130561Sobrien union internal_auxent *, void *); 9733965Sjdpstatic debug_type parse_coff_enum_type 98130561Sobrien (bfd *, struct coff_symbols *, struct coff_types *, 99130561Sobrien union internal_auxent *, void *); 100130561Sobrienstatic bfd_boolean parse_coff_symbol 101130561Sobrien (bfd *, struct coff_types *, asymbol *, long, struct internal_syment *, 102130561Sobrien void *, debug_type, bfd_boolean); 103130561Sobrienstatic bfd_boolean external_coff_symbol_p (int sym_class); 10433965Sjdp 10533965Sjdp/* Return the slot for a type. */ 10633965Sjdp 10733965Sjdpstatic debug_type * 108130561Sobriencoff_get_slot (struct coff_types *types, int indx) 10933965Sjdp{ 11033965Sjdp struct coff_slots **pps; 11133965Sjdp 11233965Sjdp pps = &types->slots; 11333965Sjdp 11433965Sjdp while (indx >= COFF_SLOTS) 11533965Sjdp { 11633965Sjdp if (*pps == NULL) 11733965Sjdp { 11833965Sjdp *pps = (struct coff_slots *) xmalloc (sizeof **pps); 11933965Sjdp memset (*pps, 0, sizeof **pps); 12033965Sjdp } 12133965Sjdp pps = &(*pps)->next; 12233965Sjdp indx -= COFF_SLOTS; 12333965Sjdp } 12433965Sjdp 12533965Sjdp if (*pps == NULL) 12633965Sjdp { 12733965Sjdp *pps = (struct coff_slots *) xmalloc (sizeof **pps); 12833965Sjdp memset (*pps, 0, sizeof **pps); 12933965Sjdp } 13033965Sjdp 13133965Sjdp return (*pps)->slots + indx; 13233965Sjdp} 13333965Sjdp 13433965Sjdp/* Parse a COFF type code in NTYPE. */ 13533965Sjdp 13633965Sjdpstatic debug_type 137130561Sobrienparse_coff_type (bfd *abfd, struct coff_symbols *symbols, 138130561Sobrien struct coff_types *types, long coff_symno, int ntype, 139130561Sobrien union internal_auxent *pauxent, bfd_boolean useaux, 140130561Sobrien void *dhandle) 14133965Sjdp{ 14233965Sjdp debug_type type; 14333965Sjdp 14433965Sjdp if ((ntype & ~N_BTMASK) != 0) 14533965Sjdp { 14633965Sjdp int newtype; 14733965Sjdp 14833965Sjdp newtype = DECREF (ntype); 14933965Sjdp 15033965Sjdp if (ISPTR (ntype)) 15133965Sjdp { 15233965Sjdp type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, 15333965Sjdp pauxent, useaux, dhandle); 15433965Sjdp type = debug_make_pointer_type (dhandle, type); 15533965Sjdp } 15633965Sjdp else if (ISFCN (ntype)) 15733965Sjdp { 15833965Sjdp type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, 15933965Sjdp pauxent, useaux, dhandle); 16033965Sjdp type = debug_make_function_type (dhandle, type, (debug_type *) NULL, 161130561Sobrien FALSE); 16233965Sjdp } 16333965Sjdp else if (ISARY (ntype)) 16433965Sjdp { 16533965Sjdp int n; 16633965Sjdp 16733965Sjdp if (pauxent == NULL) 16833965Sjdp n = 0; 16933965Sjdp else 17033965Sjdp { 17133965Sjdp unsigned short *dim; 17233965Sjdp int i; 17333965Sjdp 17433965Sjdp /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets 17533965Sjdp the c_naux field of the syment to 0. */ 17633965Sjdp 17733965Sjdp /* Move the dimensions down, so that the next array 17833965Sjdp picks up the next one. */ 17933965Sjdp dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen; 18033965Sjdp n = dim[0]; 18133965Sjdp for (i = 0; *dim != 0 && i < DIMNUM - 1; i++, dim++) 18233965Sjdp *dim = *(dim + 1); 18333965Sjdp *dim = 0; 18433965Sjdp } 18533965Sjdp 18633965Sjdp type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, 187130561Sobrien pauxent, FALSE, dhandle); 18833965Sjdp type = debug_make_array_type (dhandle, type, 18933965Sjdp parse_coff_base_type (abfd, symbols, 19033965Sjdp types, 19133965Sjdp coff_symno, 19233965Sjdp T_INT, 19333965Sjdp NULL, dhandle), 194130561Sobrien 0, n - 1, FALSE); 19533965Sjdp } 19633965Sjdp else 19733965Sjdp { 19860484Sobrien non_fatal (_("parse_coff_type: Bad type code 0x%x"), ntype); 19933965Sjdp return DEBUG_TYPE_NULL; 20033965Sjdp } 20133965Sjdp 20233965Sjdp return type; 20333965Sjdp } 20433965Sjdp 20533965Sjdp if (pauxent != NULL && pauxent->x_sym.x_tagndx.l > 0) 20633965Sjdp { 20733965Sjdp debug_type *slot; 20833965Sjdp 20933965Sjdp /* This is a reference to an existing type. FIXME: gdb checks 21033965Sjdp that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG. */ 21133965Sjdp slot = coff_get_slot (types, pauxent->x_sym.x_tagndx.l); 21233965Sjdp if (*slot != DEBUG_TYPE_NULL) 21333965Sjdp return *slot; 21433965Sjdp else 21533965Sjdp return debug_make_indirect_type (dhandle, slot, (const char *) NULL); 21633965Sjdp } 21733965Sjdp 21833965Sjdp /* If the aux entry has already been used for something, useaux will 21933965Sjdp have been set to false, indicating that parse_coff_base_type 22033965Sjdp should not use it. We need to do it this way, rather than simply 22133965Sjdp passing pauxent as NULL, because we need to be able handle 22233965Sjdp multiple array dimensions while still discarding pauxent after 22333965Sjdp having handled all of them. */ 22433965Sjdp if (! useaux) 22533965Sjdp pauxent = NULL; 22633965Sjdp 22733965Sjdp return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, 22833965Sjdp pauxent, dhandle); 22933965Sjdp} 23033965Sjdp 23133965Sjdp/* Parse a basic COFF type in NTYPE. */ 23233965Sjdp 23333965Sjdpstatic debug_type 234130561Sobrienparse_coff_base_type (bfd *abfd, struct coff_symbols *symbols, 235130561Sobrien struct coff_types *types, long coff_symno, int ntype, 236130561Sobrien union internal_auxent *pauxent, void *dhandle) 23733965Sjdp{ 23833965Sjdp debug_type ret; 239130561Sobrien bfd_boolean set_basic; 24033965Sjdp const char *name; 24133965Sjdp debug_type *slot; 24233965Sjdp 24333965Sjdp if (ntype >= 0 24433965Sjdp && ntype <= T_MAX 24533965Sjdp && types->basic[ntype] != DEBUG_TYPE_NULL) 24633965Sjdp return types->basic[ntype]; 24733965Sjdp 248130561Sobrien set_basic = TRUE; 24933965Sjdp name = NULL; 25033965Sjdp 25133965Sjdp switch (ntype) 25233965Sjdp { 25333965Sjdp default: 25433965Sjdp ret = debug_make_void_type (dhandle); 25533965Sjdp break; 25633965Sjdp 25733965Sjdp case T_NULL: 25833965Sjdp case T_VOID: 25933965Sjdp ret = debug_make_void_type (dhandle); 26033965Sjdp name = "void"; 26133965Sjdp break; 26233965Sjdp 26333965Sjdp case T_CHAR: 264130561Sobrien ret = debug_make_int_type (dhandle, 1, FALSE); 26533965Sjdp name = "char"; 26633965Sjdp break; 26733965Sjdp 26833965Sjdp case T_SHORT: 269130561Sobrien ret = debug_make_int_type (dhandle, 2, FALSE); 27033965Sjdp name = "short"; 27133965Sjdp break; 27233965Sjdp 27333965Sjdp case T_INT: 27433965Sjdp /* FIXME: Perhaps the size should depend upon the architecture. */ 275130561Sobrien ret = debug_make_int_type (dhandle, 4, FALSE); 27633965Sjdp name = "int"; 27733965Sjdp break; 27833965Sjdp 27933965Sjdp case T_LONG: 280130561Sobrien ret = debug_make_int_type (dhandle, 4, FALSE); 28133965Sjdp name = "long"; 28233965Sjdp break; 28333965Sjdp 28433965Sjdp case T_FLOAT: 28533965Sjdp ret = debug_make_float_type (dhandle, 4); 28633965Sjdp name = "float"; 28733965Sjdp break; 28833965Sjdp 28933965Sjdp case T_DOUBLE: 29033965Sjdp ret = debug_make_float_type (dhandle, 8); 29133965Sjdp name = "double"; 29233965Sjdp break; 29333965Sjdp 29433965Sjdp case T_LNGDBL: 29533965Sjdp ret = debug_make_float_type (dhandle, 12); 29633965Sjdp name = "long double"; 29733965Sjdp break; 29833965Sjdp 29933965Sjdp case T_UCHAR: 300130561Sobrien ret = debug_make_int_type (dhandle, 1, TRUE); 30133965Sjdp name = "unsigned char"; 30233965Sjdp break; 30333965Sjdp 30433965Sjdp case T_USHORT: 305130561Sobrien ret = debug_make_int_type (dhandle, 2, TRUE); 30633965Sjdp name = "unsigned short"; 30733965Sjdp break; 30833965Sjdp 30933965Sjdp case T_UINT: 310130561Sobrien ret = debug_make_int_type (dhandle, 4, TRUE); 31133965Sjdp name = "unsigned int"; 31233965Sjdp break; 31333965Sjdp 31433965Sjdp case T_ULONG: 315130561Sobrien ret = debug_make_int_type (dhandle, 4, TRUE); 31633965Sjdp name = "unsigned long"; 31733965Sjdp break; 31833965Sjdp 31933965Sjdp case T_STRUCT: 32033965Sjdp if (pauxent == NULL) 321130561Sobrien ret = debug_make_struct_type (dhandle, TRUE, 0, 32233965Sjdp (debug_field *) NULL); 32333965Sjdp else 32433965Sjdp ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, 32533965Sjdp dhandle); 32633965Sjdp 32733965Sjdp slot = coff_get_slot (types, coff_symno); 32833965Sjdp *slot = ret; 32933965Sjdp 330130561Sobrien set_basic = FALSE; 33133965Sjdp break; 33233965Sjdp 33333965Sjdp case T_UNION: 33433965Sjdp if (pauxent == NULL) 335130561Sobrien ret = debug_make_struct_type (dhandle, FALSE, 0, (debug_field *) NULL); 33633965Sjdp else 33733965Sjdp ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, 33833965Sjdp dhandle); 33933965Sjdp 34033965Sjdp slot = coff_get_slot (types, coff_symno); 34133965Sjdp *slot = ret; 34233965Sjdp 343130561Sobrien set_basic = FALSE; 34433965Sjdp break; 34533965Sjdp 34633965Sjdp case T_ENUM: 34733965Sjdp if (pauxent == NULL) 34833965Sjdp ret = debug_make_enum_type (dhandle, (const char **) NULL, 34933965Sjdp (bfd_signed_vma *) NULL); 35033965Sjdp else 35133965Sjdp ret = parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle); 35233965Sjdp 35333965Sjdp slot = coff_get_slot (types, coff_symno); 35433965Sjdp *slot = ret; 35533965Sjdp 356130561Sobrien set_basic = FALSE; 35733965Sjdp break; 35833965Sjdp } 35933965Sjdp 36033965Sjdp if (name != NULL) 36133965Sjdp ret = debug_name_type (dhandle, name, ret); 36233965Sjdp 36333965Sjdp if (set_basic 36433965Sjdp && ntype >= 0 36533965Sjdp && ntype <= T_MAX) 36633965Sjdp types->basic[ntype] = ret; 36733965Sjdp 36833965Sjdp return ret; 36933965Sjdp} 37033965Sjdp 37133965Sjdp/* Parse a struct type. */ 37233965Sjdp 37333965Sjdpstatic debug_type 374130561Sobrienparse_coff_struct_type (bfd *abfd, struct coff_symbols *symbols, 375130561Sobrien struct coff_types *types, int ntype, 376130561Sobrien union internal_auxent *pauxent, void *dhandle) 37733965Sjdp{ 37833965Sjdp long symend; 37933965Sjdp int alloc; 38033965Sjdp debug_field *fields; 38133965Sjdp int count; 382130561Sobrien bfd_boolean done; 38333965Sjdp 38433965Sjdp symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l; 38533965Sjdp 38633965Sjdp alloc = 10; 38733965Sjdp fields = (debug_field *) xmalloc (alloc * sizeof *fields); 38833965Sjdp count = 0; 38933965Sjdp 390130561Sobrien done = FALSE; 39133965Sjdp while (! done 39233965Sjdp && symbols->coff_symno < symend 39333965Sjdp && symbols->symno < symbols->symcount) 39433965Sjdp { 39533965Sjdp asymbol *sym; 39633965Sjdp long this_coff_symno; 39733965Sjdp struct internal_syment syment; 39833965Sjdp union internal_auxent auxent; 39933965Sjdp union internal_auxent *psubaux; 40033965Sjdp bfd_vma bitpos = 0, bitsize = 0; 40133965Sjdp 40233965Sjdp sym = symbols->syms[symbols->symno]; 40333965Sjdp 40433965Sjdp if (! bfd_coff_get_syment (abfd, sym, &syment)) 40533965Sjdp { 40660484Sobrien non_fatal (_("bfd_coff_get_syment failed: %s"), 40760484Sobrien bfd_errmsg (bfd_get_error ())); 40833965Sjdp return DEBUG_TYPE_NULL; 40933965Sjdp } 41033965Sjdp 41133965Sjdp this_coff_symno = symbols->coff_symno; 41233965Sjdp 41333965Sjdp ++symbols->symno; 41433965Sjdp symbols->coff_symno += 1 + syment.n_numaux; 41533965Sjdp 41633965Sjdp if (syment.n_numaux == 0) 41733965Sjdp psubaux = NULL; 41833965Sjdp else 41933965Sjdp { 42033965Sjdp if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent)) 42133965Sjdp { 42260484Sobrien non_fatal (_("bfd_coff_get_auxent failed: %s"), 42360484Sobrien bfd_errmsg (bfd_get_error ())); 42433965Sjdp return DEBUG_TYPE_NULL; 42533965Sjdp } 42633965Sjdp psubaux = &auxent; 42733965Sjdp } 42833965Sjdp 42933965Sjdp switch (syment.n_sclass) 43033965Sjdp { 43133965Sjdp case C_MOS: 43233965Sjdp case C_MOU: 43333965Sjdp bitpos = 8 * bfd_asymbol_value (sym); 43433965Sjdp bitsize = 0; 43533965Sjdp break; 43633965Sjdp 43733965Sjdp case C_FIELD: 43833965Sjdp bitpos = bfd_asymbol_value (sym); 43933965Sjdp bitsize = auxent.x_sym.x_misc.x_lnsz.x_size; 44033965Sjdp break; 44133965Sjdp 44233965Sjdp case C_EOS: 443130561Sobrien done = TRUE; 44433965Sjdp break; 44533965Sjdp } 44633965Sjdp 44733965Sjdp if (! done) 44833965Sjdp { 44933965Sjdp debug_type ftype; 45033965Sjdp debug_field f; 45133965Sjdp 45233965Sjdp ftype = parse_coff_type (abfd, symbols, types, this_coff_symno, 453130561Sobrien syment.n_type, psubaux, TRUE, dhandle); 45433965Sjdp f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype, 45533965Sjdp bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC); 45633965Sjdp if (f == DEBUG_FIELD_NULL) 45733965Sjdp return DEBUG_TYPE_NULL; 45833965Sjdp 45933965Sjdp if (count + 1 >= alloc) 46033965Sjdp { 46133965Sjdp alloc += 10; 46233965Sjdp fields = ((debug_field *) 46333965Sjdp xrealloc (fields, alloc * sizeof *fields)); 46433965Sjdp } 46533965Sjdp 46633965Sjdp fields[count] = f; 46733965Sjdp ++count; 46833965Sjdp } 46933965Sjdp } 47033965Sjdp 47133965Sjdp fields[count] = DEBUG_FIELD_NULL; 47233965Sjdp 47333965Sjdp return debug_make_struct_type (dhandle, ntype == T_STRUCT, 47433965Sjdp pauxent->x_sym.x_misc.x_lnsz.x_size, 47533965Sjdp fields); 47633965Sjdp} 47733965Sjdp 47833965Sjdp/* Parse an enum type. */ 47933965Sjdp 48033965Sjdpstatic debug_type 481130561Sobrienparse_coff_enum_type (bfd *abfd, struct coff_symbols *symbols, 482130561Sobrien struct coff_types *types ATTRIBUTE_UNUSED, 483130561Sobrien union internal_auxent *pauxent, void *dhandle) 48433965Sjdp{ 48533965Sjdp long symend; 48633965Sjdp int alloc; 48733965Sjdp const char **names; 48833965Sjdp bfd_signed_vma *vals; 48933965Sjdp int count; 490130561Sobrien bfd_boolean done; 49133965Sjdp 49233965Sjdp symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l; 49333965Sjdp 49433965Sjdp alloc = 10; 49533965Sjdp names = (const char **) xmalloc (alloc * sizeof *names); 49633965Sjdp vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *vals); 49733965Sjdp count = 0; 49833965Sjdp 499130561Sobrien done = FALSE; 50033965Sjdp while (! done 50133965Sjdp && symbols->coff_symno < symend 50233965Sjdp && symbols->symno < symbols->symcount) 50333965Sjdp { 50433965Sjdp asymbol *sym; 50533965Sjdp struct internal_syment syment; 50633965Sjdp 50733965Sjdp sym = symbols->syms[symbols->symno]; 50833965Sjdp 50933965Sjdp if (! bfd_coff_get_syment (abfd, sym, &syment)) 51033965Sjdp { 51160484Sobrien non_fatal (_("bfd_coff_get_syment failed: %s"), 51260484Sobrien bfd_errmsg (bfd_get_error ())); 51333965Sjdp return DEBUG_TYPE_NULL; 51433965Sjdp } 51533965Sjdp 51633965Sjdp ++symbols->symno; 51733965Sjdp symbols->coff_symno += 1 + syment.n_numaux; 51833965Sjdp 51933965Sjdp switch (syment.n_sclass) 52033965Sjdp { 52133965Sjdp case C_MOE: 52233965Sjdp if (count + 1 >= alloc) 52333965Sjdp { 52433965Sjdp alloc += 10; 52533965Sjdp names = ((const char **) 52633965Sjdp xrealloc (names, alloc * sizeof *names)); 52733965Sjdp vals = ((bfd_signed_vma *) 52833965Sjdp xrealloc (vals, alloc * sizeof *vals)); 52933965Sjdp } 53033965Sjdp 53133965Sjdp names[count] = bfd_asymbol_name (sym); 53233965Sjdp vals[count] = bfd_asymbol_value (sym); 53333965Sjdp ++count; 53433965Sjdp break; 53533965Sjdp 53633965Sjdp case C_EOS: 537130561Sobrien done = TRUE; 53833965Sjdp break; 53933965Sjdp } 54033965Sjdp } 54133965Sjdp 54233965Sjdp names[count] = NULL; 54333965Sjdp 54433965Sjdp return debug_make_enum_type (dhandle, names, vals); 54533965Sjdp} 54633965Sjdp 54733965Sjdp/* Handle a single COFF symbol. */ 54833965Sjdp 549130561Sobrienstatic bfd_boolean 550130561Sobrienparse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types, 551130561Sobrien asymbol *sym, long coff_symno, 552130561Sobrien struct internal_syment *psyment, void *dhandle, 553130561Sobrien debug_type type, bfd_boolean within_function) 55433965Sjdp{ 55533965Sjdp switch (psyment->n_sclass) 55633965Sjdp { 55733965Sjdp case C_NULL: 55833965Sjdp break; 55933965Sjdp 56033965Sjdp case C_AUTO: 56133965Sjdp if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, 56233965Sjdp DEBUG_LOCAL, bfd_asymbol_value (sym))) 563130561Sobrien return FALSE; 56433965Sjdp break; 56533965Sjdp 56677298Sobrien case C_WEAKEXT: 56733965Sjdp case C_EXT: 56833965Sjdp if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, 56933965Sjdp DEBUG_GLOBAL, bfd_asymbol_value (sym))) 570130561Sobrien return FALSE; 57133965Sjdp break; 57233965Sjdp 57333965Sjdp case C_STAT: 57433965Sjdp if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, 57533965Sjdp (within_function 57633965Sjdp ? DEBUG_LOCAL_STATIC 57733965Sjdp : DEBUG_STATIC), 57833965Sjdp bfd_asymbol_value (sym))) 579130561Sobrien return FALSE; 58033965Sjdp break; 58133965Sjdp 58233965Sjdp case C_REG: 58333965Sjdp /* FIXME: We may need to convert the register number. */ 58433965Sjdp if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, 58533965Sjdp DEBUG_REGISTER, bfd_asymbol_value (sym))) 586130561Sobrien return FALSE; 58733965Sjdp break; 58833965Sjdp 58933965Sjdp case C_LABEL: 59033965Sjdp break; 59133965Sjdp 59233965Sjdp case C_ARG: 59333965Sjdp if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type, 59433965Sjdp DEBUG_PARM_STACK, bfd_asymbol_value (sym))) 595130561Sobrien return FALSE; 59633965Sjdp break; 59733965Sjdp 59833965Sjdp case C_REGPARM: 59933965Sjdp /* FIXME: We may need to convert the register number. */ 60033965Sjdp if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type, 60133965Sjdp DEBUG_PARM_REG, bfd_asymbol_value (sym))) 602130561Sobrien return FALSE; 60333965Sjdp break; 60433965Sjdp 60533965Sjdp case C_TPDEF: 60633965Sjdp type = debug_name_type (dhandle, bfd_asymbol_name (sym), type); 60733965Sjdp if (type == DEBUG_TYPE_NULL) 608130561Sobrien return FALSE; 60933965Sjdp break; 61033965Sjdp 61133965Sjdp case C_STRTAG: 61233965Sjdp case C_UNTAG: 61333965Sjdp case C_ENTAG: 61433965Sjdp { 61533965Sjdp debug_type *slot; 61633965Sjdp 61733965Sjdp type = debug_tag_type (dhandle, bfd_asymbol_name (sym), type); 61833965Sjdp if (type == DEBUG_TYPE_NULL) 619130561Sobrien return FALSE; 62033965Sjdp 62133965Sjdp /* Store the named type into the slot, so that references get 62233965Sjdp the name. */ 62333965Sjdp slot = coff_get_slot (types, coff_symno); 62433965Sjdp *slot = type; 62533965Sjdp } 62633965Sjdp break; 62733965Sjdp 62833965Sjdp default: 62933965Sjdp break; 63033965Sjdp } 63133965Sjdp 632130561Sobrien return TRUE; 63333965Sjdp} 63433965Sjdp 63577298Sobrien/* Determine if a symbol has external visibility. */ 63677298Sobrien 637130561Sobrienstatic bfd_boolean 638130561Sobrienexternal_coff_symbol_p (int sym_class) 63977298Sobrien{ 64077298Sobrien switch (sym_class) 64177298Sobrien { 642104834Sobrien case C_EXT: 643104834Sobrien case C_WEAKEXT: 644130561Sobrien return TRUE; 64577298Sobrien default: 64677298Sobrien break; 64777298Sobrien } 648130561Sobrien return FALSE; 64977298Sobrien} 65077298Sobrien 65133965Sjdp/* This is the main routine. It looks through all the symbols and 65233965Sjdp handles them. */ 65333965Sjdp 654130561Sobrienbfd_boolean 655130561Sobrienparse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle) 65633965Sjdp{ 65733965Sjdp struct coff_symbols symbols; 65833965Sjdp struct coff_types types; 65933965Sjdp int i; 66033965Sjdp long next_c_file; 66133965Sjdp const char *fnname; 66233965Sjdp int fnclass; 66333965Sjdp int fntype; 66433965Sjdp bfd_vma fnend; 66533965Sjdp alent *linenos; 666130561Sobrien bfd_boolean within_function; 66733965Sjdp long this_coff_symno; 66833965Sjdp 66933965Sjdp symbols.syms = syms; 67033965Sjdp symbols.symcount = symcount; 67133965Sjdp symbols.symno = 0; 67233965Sjdp symbols.coff_symno = 0; 67333965Sjdp 67433965Sjdp types.slots = NULL; 67533965Sjdp for (i = 0; i <= T_MAX; i++) 67633965Sjdp types.basic[i] = DEBUG_TYPE_NULL; 67733965Sjdp 67833965Sjdp next_c_file = -1; 67933965Sjdp fnname = NULL; 68033965Sjdp fnclass = 0; 68133965Sjdp fntype = 0; 68233965Sjdp fnend = 0; 68333965Sjdp linenos = NULL; 684130561Sobrien within_function = FALSE; 68533965Sjdp 68633965Sjdp while (symbols.symno < symcount) 68733965Sjdp { 68833965Sjdp asymbol *sym; 68933965Sjdp const char *name; 69033965Sjdp struct internal_syment syment; 69133965Sjdp union internal_auxent auxent; 69233965Sjdp union internal_auxent *paux; 69333965Sjdp debug_type type; 69433965Sjdp 69533965Sjdp sym = syms[symbols.symno]; 69633965Sjdp 69733965Sjdp if (! bfd_coff_get_syment (abfd, sym, &syment)) 69833965Sjdp { 69960484Sobrien non_fatal (_("bfd_coff_get_syment failed: %s"), 70060484Sobrien bfd_errmsg (bfd_get_error ())); 701130561Sobrien return FALSE; 70233965Sjdp } 70333965Sjdp 70433965Sjdp name = bfd_asymbol_name (sym); 70533965Sjdp 70633965Sjdp this_coff_symno = symbols.coff_symno; 70733965Sjdp 70833965Sjdp ++symbols.symno; 70933965Sjdp symbols.coff_symno += 1 + syment.n_numaux; 71033965Sjdp 71133965Sjdp /* We only worry about the first auxent, because that is the 71233965Sjdp only one which is relevant for debugging information. */ 71333965Sjdp if (syment.n_numaux == 0) 71433965Sjdp paux = NULL; 71533965Sjdp else 71633965Sjdp { 71733965Sjdp if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent)) 71833965Sjdp { 71960484Sobrien non_fatal (_("bfd_coff_get_auxent failed: %s"), 72060484Sobrien bfd_errmsg (bfd_get_error ())); 721130561Sobrien return FALSE; 72233965Sjdp } 72333965Sjdp paux = &auxent; 72433965Sjdp } 72533965Sjdp 72633965Sjdp if (this_coff_symno == next_c_file && syment.n_sclass != C_FILE) 72733965Sjdp { 72833965Sjdp /* The last C_FILE symbol points to the first external 72933965Sjdp symbol. */ 73033965Sjdp if (! debug_set_filename (dhandle, "*globals*")) 731130561Sobrien return FALSE; 73233965Sjdp } 73333965Sjdp 73433965Sjdp switch (syment.n_sclass) 73533965Sjdp { 73633965Sjdp case C_EFCN: 73733965Sjdp case C_EXTDEF: 73833965Sjdp case C_ULABEL: 73933965Sjdp case C_USTATIC: 74033965Sjdp case C_LINE: 74133965Sjdp case C_ALIAS: 74233965Sjdp case C_HIDDEN: 74333965Sjdp /* Just ignore these classes. */ 74433965Sjdp break; 74533965Sjdp 74633965Sjdp case C_FILE: 74733965Sjdp next_c_file = syment.n_value; 74833965Sjdp if (! debug_set_filename (dhandle, name)) 749130561Sobrien return FALSE; 75033965Sjdp break; 75133965Sjdp 75233965Sjdp case C_STAT: 75333965Sjdp /* Ignore static symbols with a type of T_NULL. These 75433965Sjdp represent section entries. */ 75533965Sjdp if (syment.n_type == T_NULL) 75633965Sjdp break; 75733965Sjdp /* Fall through. */ 758104834Sobrien case C_WEAKEXT: 75933965Sjdp case C_EXT: 76033965Sjdp if (ISFCN (syment.n_type)) 76133965Sjdp { 76233965Sjdp fnname = name; 76333965Sjdp fnclass = syment.n_sclass; 76433965Sjdp fntype = syment.n_type; 76533965Sjdp if (syment.n_numaux > 0) 76633965Sjdp fnend = bfd_asymbol_value (sym) + auxent.x_sym.x_misc.x_fsize; 76733965Sjdp else 76833965Sjdp fnend = 0; 76933965Sjdp linenos = BFD_SEND (abfd, _get_lineno, (abfd, sym)); 77033965Sjdp break; 77133965Sjdp } 77233965Sjdp type = parse_coff_type (abfd, &symbols, &types, this_coff_symno, 773130561Sobrien syment.n_type, paux, TRUE, dhandle); 77433965Sjdp if (type == DEBUG_TYPE_NULL) 775130561Sobrien return FALSE; 77633965Sjdp if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment, 77733965Sjdp dhandle, type, within_function)) 778130561Sobrien return FALSE; 77933965Sjdp break; 78033965Sjdp 78133965Sjdp case C_FCN: 78233965Sjdp if (strcmp (name, ".bf") == 0) 78333965Sjdp { 78433965Sjdp if (fnname == NULL) 78533965Sjdp { 78660484Sobrien non_fatal (_("%ld: .bf without preceding function"), 78760484Sobrien this_coff_symno); 788130561Sobrien return FALSE; 78933965Sjdp } 79033965Sjdp 79133965Sjdp type = parse_coff_type (abfd, &symbols, &types, this_coff_symno, 792130561Sobrien DECREF (fntype), paux, FALSE, dhandle); 79333965Sjdp if (type == DEBUG_TYPE_NULL) 794130561Sobrien return FALSE; 79533965Sjdp 79633965Sjdp if (! debug_record_function (dhandle, fnname, type, 79777298Sobrien external_coff_symbol_p (fnclass), 79833965Sjdp bfd_asymbol_value (sym))) 799130561Sobrien return FALSE; 80033965Sjdp 80133965Sjdp if (linenos != NULL) 80233965Sjdp { 80333965Sjdp int base; 80433965Sjdp bfd_vma addr; 80533965Sjdp 80633965Sjdp if (syment.n_numaux == 0) 80733965Sjdp base = 0; 80833965Sjdp else 80933965Sjdp base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1; 81033965Sjdp 81133965Sjdp addr = bfd_get_section_vma (abfd, bfd_get_section (sym)); 81233965Sjdp 81333965Sjdp ++linenos; 81433965Sjdp 81533965Sjdp while (linenos->line_number != 0) 81633965Sjdp { 81733965Sjdp if (! debug_record_line (dhandle, 81833965Sjdp linenos->line_number + base, 81933965Sjdp linenos->u.offset + addr)) 820130561Sobrien return FALSE; 82133965Sjdp ++linenos; 82233965Sjdp } 82333965Sjdp } 82433965Sjdp 82533965Sjdp fnname = NULL; 82633965Sjdp linenos = NULL; 82733965Sjdp fnclass = 0; 82833965Sjdp fntype = 0; 82933965Sjdp 830130561Sobrien within_function = TRUE; 83133965Sjdp } 83233965Sjdp else if (strcmp (name, ".ef") == 0) 83333965Sjdp { 83433965Sjdp if (! within_function) 83533965Sjdp { 83660484Sobrien non_fatal (_("%ld: unexpected .ef\n"), this_coff_symno); 837130561Sobrien return FALSE; 83833965Sjdp } 83933965Sjdp 84033965Sjdp if (bfd_asymbol_value (sym) > fnend) 84133965Sjdp fnend = bfd_asymbol_value (sym); 84233965Sjdp if (! debug_end_function (dhandle, fnend)) 843130561Sobrien return FALSE; 84433965Sjdp 84533965Sjdp fnend = 0; 846130561Sobrien within_function = FALSE; 84733965Sjdp } 84833965Sjdp break; 84933965Sjdp 85033965Sjdp case C_BLOCK: 85133965Sjdp if (strcmp (name, ".bb") == 0) 85233965Sjdp { 85333965Sjdp if (! debug_start_block (dhandle, bfd_asymbol_value (sym))) 854130561Sobrien return FALSE; 85533965Sjdp } 85633965Sjdp else if (strcmp (name, ".eb") == 0) 85733965Sjdp { 85833965Sjdp if (! debug_end_block (dhandle, bfd_asymbol_value (sym))) 859130561Sobrien return FALSE; 86033965Sjdp } 86133965Sjdp break; 86233965Sjdp 86333965Sjdp default: 86433965Sjdp type = parse_coff_type (abfd, &symbols, &types, this_coff_symno, 865130561Sobrien syment.n_type, paux, TRUE, dhandle); 86633965Sjdp if (type == DEBUG_TYPE_NULL) 867130561Sobrien return FALSE; 86833965Sjdp if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment, 86933965Sjdp dhandle, type, within_function)) 870130561Sobrien return FALSE; 87133965Sjdp break; 87233965Sjdp } 87333965Sjdp } 87433965Sjdp 875130561Sobrien return TRUE; 87633965Sjdp} 877