X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Frdcoff.c;h=006f13b3aa015d96e2c25c89145bfe6313b806f1;hb=d043f8c867f85f1c36cc957da8204fe2907b3aea;hp=9f7660b278e95699a6d809810d93d9b4110f2fb1;hpb=fa803dc60f0bf01297674c41d001798e18ade4dc;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/rdcoff.c b/binutils/rdcoff.c index 9f7660b278..006f13b3aa 100644 --- a/binutils/rdcoff.c +++ b/binutils/rdcoff.c @@ -1,12 +1,12 @@ /* stabs.c -- Parse COFF debugging information - Copyright (C) 1996 Free Software Foundation, Inc. + Copyright (C) 1996-2019 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -16,16 +16,16 @@ 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. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ /* This file contains code which parses COFF debugging information. */ +#include "sysdep.h" #include "bfd.h" #include "coff/internal.h" -#include "bucomm.h" #include "libiberty.h" -#include "demangle.h" +#include "bucomm.h" #include "debug.h" #include "budbg.h" @@ -83,34 +83,38 @@ struct coff_types debug_type basic[T_MAX + 1]; }; -static debug_type *coff_get_slot PARAMS ((struct coff_types *, int)); +static debug_type *coff_get_slot (struct coff_types *, long); static debug_type parse_coff_type - PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, long, int, - union internal_auxent *, boolean, PTR)); + (bfd *, struct coff_symbols *, struct coff_types *, long, int, + union internal_auxent *, bfd_boolean, void *); static debug_type parse_coff_base_type - PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, long, int, - union internal_auxent *, PTR)); + (bfd *, struct coff_symbols *, struct coff_types *, long, int, + union internal_auxent *, void *); static debug_type parse_coff_struct_type - PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, int, - union internal_auxent *, PTR)); + (bfd *, struct coff_symbols *, struct coff_types *, int, + union internal_auxent *, void *); 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)); + (bfd *, struct coff_symbols *, struct coff_types *, + union internal_auxent *, void *); +static bfd_boolean parse_coff_symbol + (bfd *, struct coff_types *, asymbol *, long, struct internal_syment *, + void *, debug_type, bfd_boolean); +static bfd_boolean external_coff_symbol_p (int sym_class); /* Return the slot for a type. */ static debug_type * -coff_get_slot (types, indx) - struct coff_types *types; - int indx; +coff_get_slot (struct coff_types *types, long indx) { struct coff_slots **pps; pps = &types->slots; + /* PR 17512: file: 078-18333-0.001:0.1. + FIXME: The value of 1000 is a guess. Maybe a better heuristic is needed. */ + if (indx / COFF_SLOTS > 1000) + fatal (_("Excessively large slot index: %lx"), indx); + while (indx >= COFF_SLOTS) { if (*pps == NULL) @@ -134,16 +138,10 @@ coff_get_slot (types, 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; +parse_coff_type (bfd *abfd, struct coff_symbols *symbols, + struct coff_types *types, long coff_symno, int ntype, + union internal_auxent *pauxent, bfd_boolean useaux, + void *dhandle) { debug_type type; @@ -164,7 +162,7 @@ parse_coff_type (abfd, symbols, types, coff_symno, ntype, pauxent, useaux, type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, pauxent, useaux, dhandle); type = debug_make_function_type (dhandle, type, (debug_type *) NULL, - false); + FALSE); } else if (ISARY (ntype)) { @@ -190,14 +188,19 @@ parse_coff_type (abfd, symbols, types, coff_symno, ntype, pauxent, useaux, } type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, - pauxent, false, dhandle); + 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); + 0, n - 1, FALSE); + } + else + { + non_fatal (_("parse_coff_type: Bad type code 0x%x"), ntype); + return DEBUG_TYPE_NULL; } return type; @@ -232,18 +235,12 @@ parse_coff_type (abfd, symbols, types, coff_symno, ntype, pauxent, useaux, /* 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; +parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols, + struct coff_types *types, long coff_symno, int ntype, + union internal_auxent *pauxent, void *dhandle) { debug_type ret; - boolean set_basic; + bfd_boolean set_basic; const char *name; debug_type *slot; @@ -252,7 +249,7 @@ parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent, && types->basic[ntype] != DEBUG_TYPE_NULL) return types->basic[ntype]; - set_basic = true; + set_basic = TRUE; name = NULL; switch (ntype) @@ -268,23 +265,23 @@ parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent, break; case T_CHAR: - ret = debug_make_int_type (dhandle, 1, false); + ret = debug_make_int_type (dhandle, 1, FALSE); name = "char"; break; case T_SHORT: - ret = debug_make_int_type (dhandle, 2, false); + 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); + ret = debug_make_int_type (dhandle, 4, FALSE); name = "int"; break; case T_LONG: - ret = debug_make_int_type (dhandle, 4, false); + ret = debug_make_int_type (dhandle, 4, FALSE); name = "long"; break; @@ -304,28 +301,28 @@ parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent, break; case T_UCHAR: - ret = debug_make_int_type (dhandle, 1, true); + ret = debug_make_int_type (dhandle, 1, TRUE); name = "unsigned char"; break; case T_USHORT: - ret = debug_make_int_type (dhandle, 2, true); + ret = debug_make_int_type (dhandle, 2, TRUE); name = "unsigned short"; break; case T_UINT: - ret = debug_make_int_type (dhandle, 4, true); + ret = debug_make_int_type (dhandle, 4, TRUE); name = "unsigned int"; break; case T_ULONG: - ret = debug_make_int_type (dhandle, 4, true); + 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, + ret = debug_make_struct_type (dhandle, TRUE, 0, (debug_field *) NULL); else ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, @@ -334,12 +331,12 @@ parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent, slot = coff_get_slot (types, coff_symno); *slot = ret; - set_basic = false; + set_basic = FALSE; break; case T_UNION: if (pauxent == NULL) - ret = debug_make_struct_type (dhandle, false, 0, (debug_field *) NULL); + ret = debug_make_struct_type (dhandle, FALSE, 0, (debug_field *) NULL); else ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle); @@ -347,7 +344,7 @@ parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent, slot = coff_get_slot (types, coff_symno); *slot = ret; - set_basic = false; + set_basic = FALSE; break; case T_ENUM: @@ -360,7 +357,7 @@ parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent, slot = coff_get_slot (types, coff_symno); *slot = ret; - set_basic = false; + set_basic = FALSE; break; } @@ -378,19 +375,15 @@ parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent, /* 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; +parse_coff_struct_type (bfd *abfd, struct coff_symbols *symbols, + struct coff_types *types, int ntype, + union internal_auxent *pauxent, void *dhandle) { long symend; int alloc; debug_field *fields; int count; - boolean done; + bfd_boolean done; symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l; @@ -398,7 +391,7 @@ parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle) fields = (debug_field *) xmalloc (alloc * sizeof *fields); count = 0; - done = false; + done = FALSE; while (! done && symbols->coff_symno < symend && symbols->symno < symbols->symcount) @@ -414,8 +407,9 @@ parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle) 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 ())); + non_fatal (_("bfd_coff_get_syment failed: %s"), + bfd_errmsg (bfd_get_error ())); + free (fields); return DEBUG_TYPE_NULL; } @@ -430,8 +424,9 @@ parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle) { 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 ())); + non_fatal (_("bfd_coff_get_auxent failed: %s"), + bfd_errmsg (bfd_get_error ())); + free (fields); return DEBUG_TYPE_NULL; } psubaux = &auxent; @@ -451,7 +446,7 @@ parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle) break; case C_EOS: - done = true; + done = TRUE; break; } @@ -461,7 +456,7 @@ parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle) debug_field f; ftype = parse_coff_type (abfd, symbols, types, this_coff_symno, - syment.n_type, psubaux, true, dhandle); + 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) @@ -489,19 +484,16 @@ parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle) /* 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; +parse_coff_enum_type (bfd *abfd, struct coff_symbols *symbols, + struct coff_types *types ATTRIBUTE_UNUSED, + union internal_auxent *pauxent, void *dhandle) { long symend; int alloc; const char **names; bfd_signed_vma *vals; int count; - boolean done; + bfd_boolean done; symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l; @@ -510,7 +502,7 @@ parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle) vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *vals); count = 0; - done = false; + done = FALSE; while (! done && symbols->coff_symno < symend && symbols->symno < symbols->symcount) @@ -522,8 +514,10 @@ parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle) 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 ())); + non_fatal (_("bfd_coff_get_syment failed: %s"), + bfd_errmsg (bfd_get_error ())); + free (names); + free (vals); return DEBUG_TYPE_NULL; } @@ -548,7 +542,7 @@ parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle) break; case C_EOS: - done = true; + done = TRUE; break; } } @@ -560,17 +554,11 @@ parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle) /* 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; +static bfd_boolean +parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types, + asymbol *sym, long coff_symno, + struct internal_syment *psyment, void *dhandle, + debug_type type, bfd_boolean within_function) { switch (psyment->n_sclass) { @@ -580,13 +568,14 @@ parse_coff_symbol (abfd, types, sym, coff_symno, psyment, dhandle, type, case C_AUTO: if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, DEBUG_LOCAL, bfd_asymbol_value (sym))) - return false; + return FALSE; break; + case C_WEAKEXT: case C_EXT: if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, DEBUG_GLOBAL, bfd_asymbol_value (sym))) - return false; + return FALSE; break; case C_STAT: @@ -595,14 +584,14 @@ parse_coff_symbol (abfd, types, sym, coff_symno, psyment, dhandle, type, ? DEBUG_LOCAL_STATIC : DEBUG_STATIC), bfd_asymbol_value (sym))) - return false; + 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; + return FALSE; break; case C_LABEL: @@ -611,20 +600,20 @@ parse_coff_symbol (abfd, types, sym, coff_symno, psyment, dhandle, type, case C_ARG: if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type, DEBUG_PARM_STACK, bfd_asymbol_value (sym))) - return false; + 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; + return FALSE; break; case C_TPDEF: type = debug_name_type (dhandle, bfd_asymbol_name (sym), type); if (type == DEBUG_TYPE_NULL) - return false; + return FALSE; break; case C_STRTAG: @@ -635,7 +624,7 @@ parse_coff_symbol (abfd, types, sym, coff_symno, psyment, dhandle, type, type = debug_tag_type (dhandle, bfd_asymbol_name (sym), type); if (type == DEBUG_TYPE_NULL) - return false; + return FALSE; /* Store the named type into the slot, so that references get the name. */ @@ -648,18 +637,30 @@ parse_coff_symbol (abfd, types, sym, coff_symno, psyment, dhandle, type, break; } - return true; + return TRUE; +} + +/* Determine if a symbol has external visibility. */ + +static bfd_boolean +external_coff_symbol_p (int sym_class) +{ + switch (sym_class) + { + case C_EXT: + case C_WEAKEXT: + return TRUE; + default: + break; + } + return FALSE; } /* 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; +bfd_boolean +parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle) { struct coff_symbols symbols; struct coff_types types; @@ -668,8 +669,9 @@ parse_coff (abfd, syms, symcount, dhandle) const char *fnname; int fnclass; int fntype; + bfd_vma fnend; alent *linenos; - boolean within_function; + bfd_boolean within_function; long this_coff_symno; symbols.syms = syms; @@ -685,8 +687,9 @@ parse_coff (abfd, syms, symcount, dhandle) fnname = NULL; fnclass = 0; fntype = 0; + fnend = 0; linenos = NULL; - within_function = false; + within_function = FALSE; while (symbols.symno < symcount) { @@ -701,9 +704,9 @@ parse_coff (abfd, syms, symcount, dhandle) 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; + non_fatal (_("bfd_coff_get_syment failed: %s"), + bfd_errmsg (bfd_get_error ())); + return FALSE; } name = bfd_asymbol_name (sym); @@ -721,9 +724,9 @@ parse_coff (abfd, syms, symcount, dhandle) { 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; + non_fatal (_("bfd_coff_get_auxent failed: %s"), + bfd_errmsg (bfd_get_error ())); + return FALSE; } paux = &auxent; } @@ -733,7 +736,7 @@ parse_coff (abfd, syms, symcount, dhandle) /* The last C_FILE symbol points to the first external symbol. */ if (! debug_set_filename (dhandle, "*globals*")) - return false; + return FALSE; } switch (syment.n_sclass) @@ -751,7 +754,7 @@ parse_coff (abfd, syms, symcount, dhandle) case C_FILE: next_c_file = syment.n_value; if (! debug_set_filename (dhandle, name)) - return false; + return FALSE; break; case C_STAT: @@ -760,22 +763,27 @@ parse_coff (abfd, syms, symcount, dhandle) if (syment.n_type == T_NULL) break; /* Fall through. */ + case C_WEAKEXT: case C_EXT: if (ISFCN (syment.n_type)) { fnname = name; fnclass = syment.n_sclass; fntype = syment.n_type; + if (syment.n_numaux > 0) + fnend = bfd_asymbol_value (sym) + auxent.x_sym.x_misc.x_fsize; + else + fnend = 0; 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); + syment.n_type, paux, TRUE, dhandle); if (type == DEBUG_TYPE_NULL) - return false; + return FALSE; if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment, dhandle, type, within_function)) - return false; + return FALSE; break; case C_FCN: @@ -783,20 +791,20 @@ parse_coff (abfd, syms, symcount, dhandle) { if (fnname == NULL) { - fprintf (stderr, "%s: %ld: .bf without preceding function\n", - program_name, this_coff_symno); - return false; + non_fatal (_("%ld: .bf without preceding function"), + this_coff_symno); + return FALSE; } type = parse_coff_type (abfd, &symbols, &types, this_coff_symno, - DECREF (fntype), paux, false, dhandle); + DECREF (fntype), paux, FALSE, dhandle); if (type == DEBUG_TYPE_NULL) - return false; + return FALSE; if (! debug_record_function (dhandle, fnname, type, - fnclass == C_EXT, + external_coff_symbol_p (fnclass), bfd_asymbol_value (sym))) - return false; + return FALSE; if (linenos != NULL) { @@ -808,7 +816,7 @@ parse_coff (abfd, syms, symcount, dhandle) else base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1; - addr = bfd_get_section_vma (abfd, bfd_get_section (sym)); + addr = bfd_section_vma (bfd_asymbol_section (sym)); ++linenos; @@ -817,7 +825,7 @@ parse_coff (abfd, syms, symcount, dhandle) if (! debug_record_line (dhandle, linenos->line_number + base, linenos->u.offset + addr)) - return false; + return FALSE; ++linenos; } } @@ -827,21 +835,23 @@ parse_coff (abfd, syms, symcount, dhandle) fnclass = 0; fntype = 0; - within_function = true; + 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; + non_fatal (_("%ld: unexpected .ef\n"), this_coff_symno); + return FALSE; } - if (! debug_end_function (dhandle, bfd_asymbol_value (sym))) - return false; + if (bfd_asymbol_value (sym) > fnend) + fnend = bfd_asymbol_value (sym); + if (! debug_end_function (dhandle, fnend)) + return FALSE; - within_function = false; + fnend = 0; + within_function = FALSE; } break; @@ -849,26 +859,26 @@ parse_coff (abfd, syms, symcount, dhandle) if (strcmp (name, ".bb") == 0) { if (! debug_start_block (dhandle, bfd_asymbol_value (sym))) - return false; + return FALSE; } else if (strcmp (name, ".eb") == 0) { if (! debug_end_block (dhandle, bfd_asymbol_value (sym))) - return false; + return FALSE; } break; default: type = parse_coff_type (abfd, &symbols, &types, this_coff_symno, - syment.n_type, paux, true, dhandle); + syment.n_type, paux, TRUE, dhandle); if (type == DEBUG_TYPE_NULL) - return false; + return FALSE; if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment, dhandle, type, within_function)) - return false; + return FALSE; break; } } - return true; + return TRUE; }