/* stabs.c -- Parse COFF debugging information
- Copyright (C) 1996, 98, 99, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1996-2023 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
+ 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,
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"
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
{
+ /* Next set of slots. */
+ struct coff_types *next;
+ /* Where the TYPES array starts. */
+ unsigned int base_index;
/* Slots. */
- struct coff_slots *slots;
- /* Basic types. */
- debug_type basic[T_MAX + 1];
+#define COFF_SLOTS (16)
+ debug_type types[COFF_SLOTS];
};
-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));
+ (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));
-static boolean external_coff_symbol_p PARAMS ((int sym_class));
+ (bfd *, struct coff_symbols *, struct coff_types **,
+ union internal_auxent *, void *);
\f
/* Return the slot for a type. */
static debug_type *
-coff_get_slot (types, indx)
- struct coff_types *types;
- int indx;
+coff_get_slot (void *dhandle, struct coff_types **types, long indx)
{
- struct coff_slots **pps;
+ unsigned int base_index;
- pps = &types->slots;
+ base_index = indx / COFF_SLOTS * COFF_SLOTS;
+ indx -= base_index;
- 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;
- }
+ while (*types && (*types)->base_index < base_index)
+ types = &(*types)->next;
- if (*pps == NULL)
+ if (*types == NULL || (*types)->base_index != base_index)
{
- *pps = (struct coff_slots *) xmalloc (sizeof **pps);
- memset (*pps, 0, sizeof **pps);
+ struct coff_types *n = debug_xzalloc (dhandle, sizeof (*n));
+ n->next = *types;
+ n->base_index = base_index;
+ *types = n;
}
- return (*pps)->slots + indx;
+ return (*types)->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, bool useaux,
+ void *dhandle)
{
debug_type type;
return type;
}
- if (pauxent != NULL && pauxent->x_sym.x_tagndx.l > 0)
+ if (pauxent != NULL && (int32_t) pauxent->x_sym.x_tagndx.u32 > 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);
+ slot = coff_get_slot (dhandle, types, pauxent->x_sym.x_tagndx.u32);
if (*slot != DEBUG_TYPE_NULL)
return *slot;
else
/* 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;
- 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;
+ const char *name = NULL;
switch (ntype)
{
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:
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:
(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;
+ debug_type *slot = coff_get_slot (dhandle, types, coff_symno);
+ *slot = 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;
+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;
+ debug_field *fields, *xfields;
int count;
- boolean done;
+ bool done;
- symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
+ symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.u32;
alloc = 10;
fields = (debug_field *) xmalloc (alloc * sizeof *fields);
{
non_fatal (_("bfd_coff_get_syment failed: %s"),
bfd_errmsg (bfd_get_error ()));
+ free (fields);
return DEBUG_TYPE_NULL;
}
{
non_fatal (_("bfd_coff_get_auxent failed: %s"),
bfd_errmsg (bfd_get_error ()));
+ free (fields);
return DEBUG_TYPE_NULL;
}
psubaux = &auxent;
case C_FIELD:
bitpos = bfd_asymbol_value (sym);
- bitsize = auxent.x_sym.x_misc.x_lnsz.x_size;
+ if (psubaux != NULL)
+ bitsize = psubaux->x_sym.x_misc.x_lnsz.x_size;
break;
case C_EOS:
f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype,
bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC);
if (f == DEBUG_FIELD_NULL)
- return DEBUG_TYPE_NULL;
+ {
+ free (fields);
+ return DEBUG_TYPE_NULL;
+ }
if (count + 1 >= alloc)
{
}
fields[count] = DEBUG_FIELD_NULL;
+ xfields = debug_xalloc (dhandle, (count + 1) * sizeof (*fields));
+ memcpy (xfields, fields, (count + 1) * sizeof (*fields));
+ free (fields);
return debug_make_struct_type (dhandle, ntype == T_STRUCT,
pauxent->x_sym.x_misc.x_lnsz.x_size,
- fields);
+ xfields);
}
/* 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 ATTRIBUTE_UNUSED;
- 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;
+ const char **names, **xnames;
+ bfd_signed_vma *vals, *xvals;
int count;
- boolean done;
+ bool done;
- symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
+ symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.u32;
alloc = 10;
names = (const char **) xmalloc (alloc * sizeof *names);
{
non_fatal (_("bfd_coff_get_syment failed: %s"),
bfd_errmsg (bfd_get_error ()));
+ free (names);
+ free (vals);
return DEBUG_TYPE_NULL;
}
}
names[count] = NULL;
-
- return debug_make_enum_type (dhandle, names, vals);
+ vals[count] = 0;
+ xnames = debug_xalloc (dhandle, (count + 1) * sizeof (*names));
+ memcpy (xnames, names, (count + 1) * sizeof (*names));
+ free (names);
+ xvals = debug_xalloc (dhandle, (count + 1) * sizeof (*vals));
+ memcpy (xvals, vals, (count + 1) * sizeof (*vals));
+ free (vals);
+
+ return debug_make_enum_type (dhandle, xnames, xvals);
}
/* Handle a single COFF symbol. */
-static boolean
-parse_coff_symbol (abfd, types, sym, coff_symno, psyment, dhandle, type,
- within_function)
- bfd *abfd ATTRIBUTE_UNUSED;
- struct coff_types *types;
- asymbol *sym;
- long coff_symno;
- struct internal_syment *psyment;
- PTR dhandle;
- debug_type type;
- boolean within_function;
+static bool
+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, bool within_function)
{
switch (psyment->n_sclass)
{
/* Store the named type into the slot, so that references get
the name. */
- slot = coff_get_slot (types, coff_symno);
+ slot = coff_get_slot (dhandle, types, coff_symno);
*slot = type;
}
break;
break;
}
- return true;
+ return true;
}
/* Determine if a symbol has external visibility. */
-static boolean
+static bool
external_coff_symbol_p (int sym_class)
{
switch (sym_class)
{
- case C_EXT:
- case C_WEAKEXT:
- return true;
+ case C_EXT:
+ case C_WEAKEXT:
+ return true;
default:
break;
}
- return false;
+ 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;
+bool
+parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle)
{
struct coff_symbols symbols;
- struct coff_types types;
- int i;
+ struct coff_types *types;
long next_c_file;
const char *fnname;
int fnclass;
int fntype;
bfd_vma fnend;
alent *linenos;
- boolean within_function;
+ bool within_function;
long this_coff_symno;
symbols.syms = syms;
symbols.symno = 0;
symbols.coff_symno = 0;
- types.slots = NULL;
- for (i = 0; i <= T_MAX; i++)
- types.basic[i] = DEBUG_TYPE_NULL;
+ types= NULL;
next_c_file = -1;
fnname = NULL;
if (syment.n_type == T_NULL)
break;
/* Fall through. */
- case C_WEAKEXT:
+ case C_WEAKEXT:
case C_EXT:
if (ISFCN (syment.n_type))
{
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;