/* Read a symbol table in ECOFF format (Third-Eye).
- Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994
+ Copyright 1986, 87, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
Free Software Foundation, Inc.
Original version contributed by Alessandro Forin (af@cs.cmu.edu) at
CMU. Major work by Per Bothner, John Gilmore and Ian Lance Taylor
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This module provides the function mdebug_build_psymtabs. It reads
ECOFF debugging information into partial symbol tables. The
#include "buildsym.h"
#include "stabsread.h"
#include "complaints.h"
-
-#if !defined (SEEK_SET)
-#define SEEK_SET 0
-#define SEEK_CUR 1
-#endif
+#include "demangle.h"
/* These are needed if the tm.h file does not contain the necessary
mips specific definitions. */
#ifndef MIPS_EFI_SYMBOL_NAME
#define MIPS_EFI_SYMBOL_NAME "__GDB_EFI_INFO__"
+extern void ecoff_relocate_efi PARAMS ((struct symbol *, CORE_ADDR));
#include "coff/sym.h"
#include "coff/symconst.h"
typedef struct mips_extra_func_info {
#include <sys/types.h>
#endif
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <string.h>
+#include "gdb_stat.h"
+#include "gdb_string.h"
#include "gdb-stabs.h"
#include "expression.h"
#include "language.h" /* Needed inside partial-stab.h */
+
/* Provide a default mapping from a ecoff register number to a gdb REGNUM. */
#ifndef ECOFF_REG_TO_REGNUM
#define ECOFF_REG_TO_REGNUM(num) (num)
#endif
-/* Each partial symbol table entry contains a pointer to private data
- for the read_symtab() function to use when expanding a partial
- symbol table entry to a full symbol table entry.
+/* Provide a way to test if we have both ECOFF and ELF symbol tables.
+ We use this define in order to know whether we should override a
+ symbol's ECOFF section with its ELF section. This is necessary in
+ case the symbol's ELF section could not be represented in ECOFF. */
+#define ECOFF_IN_ELF(bfd) (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
+ && bfd_get_section_by_name (bfd, ".mdebug") != NULL)
- For mdebugread this structure contains the index of the FDR that this
- psymtab represents and a pointer to the BFD that the psymtab was
- created from. */
-
-#define PST_PRIVATE(p) ((struct symloc *)(p)->read_symtab_private)
-#define FDR_IDX(p) (PST_PRIVATE(p)->fdr_idx)
-#define CUR_BFD(p) (PST_PRIVATE(p)->cur_bfd)
-#define DEBUG_SWAP(p) (PST_PRIVATE(p)->debug_swap)
-#define DEBUG_INFO(p) (PST_PRIVATE(p)->debug_info)
-#define PENDING_LIST(p) (PST_PRIVATE(p)->pending_list)
+\f
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
struct symloc
{
+ /* Index of the FDR that this psymtab represents. */
int fdr_idx;
+ /* The BFD that the psymtab was created from. */
bfd *cur_bfd;
const struct ecoff_debug_swap *debug_swap;
struct ecoff_debug_info *debug_info;
struct mdebug_pending **pending_list;
- EXTR *extern_tab; /* Pointer to external symbols for this file. */
- int extern_count; /* Size of extern_tab. */
+ /* Pointer to external symbols for this file. */
+ EXTR *extern_tab;
+ /* Size of extern_tab. */
+ int extern_count;
enum language pst_language;
};
+#define PST_PRIVATE(p) ((struct symloc *)(p)->read_symtab_private)
+#define FDR_IDX(p) (PST_PRIVATE(p)->fdr_idx)
+#define CUR_BFD(p) (PST_PRIVATE(p)->cur_bfd)
+#define DEBUG_SWAP(p) (PST_PRIVATE(p)->debug_swap)
+#define DEBUG_INFO(p) (PST_PRIVATE(p)->debug_info)
+#define PENDING_LIST(p) (PST_PRIVATE(p)->pending_list)
+
+#define SC_IS_TEXT(sc) ((sc) == scText \
+ || (sc) == scRConst \
+ || (sc) == scInit \
+ || (sc) == scFini)
+#define SC_IS_DATA(sc) ((sc) == scData \
+ || (sc) == scSData \
+ || (sc) == scRData \
+ || (sc) == scPData \
+ || (sc) == scXData)
+#define SC_IS_COMMON(sc) ((sc) == scCommon || (sc) == scSCommon)
+#define SC_IS_BSS(sc) ((sc) == scBss || (sc) == scSBss)
+#define SC_IS_UNDEF(sc) ((sc) == scUndefined || (sc) == scSUndefined)
+
+\f
/* Things we import explicitly from other modules */
extern int info_verbose;
static struct complaint unable_to_cross_ref_complaint =
{"unable to cross ref btTypedef for %s", 0, 0};
+static struct complaint bad_indirect_xref_complaint =
+{"unable to cross ref btIndirect for %s", 0, 0};
+
static struct complaint illegal_forward_tq0_complaint =
{"illegal tq0 in forward typedef for %s", 0, 0};
/* Note how much "debuggable" this image is. We would like
to see at least one FDR with full symbols */
-static max_gdbinfo;
-static max_glevel;
+static int max_gdbinfo;
+static int max_glevel;
/* When examining .o files, report on undefined symbols */
static char stabs_symbol[] = STABS_SYMBOL;
-/* Types corresponding to btComplex, btDComplex, etc. These are here
- rather than in gdbtypes.c or some such, because the meaning of codes
- like btComplex is specific to the mdebug debug format. FIXME: We should
- be using our own types thoughout this file, instead of sometimes using
- builtin_type_*. */
-
+/* Types corresponding to mdebug format bt* basic types. */
+
+static struct type *mdebug_type_void;
+static struct type *mdebug_type_char;
+static struct type *mdebug_type_short;
+static struct type *mdebug_type_int_32;
+#define mdebug_type_int mdebug_type_int_32
+static struct type *mdebug_type_int_64;
+static struct type *mdebug_type_long_32;
+static struct type *mdebug_type_long_64;
+static struct type *mdebug_type_long_long_64;
+static struct type *mdebug_type_unsigned_char;
+static struct type *mdebug_type_unsigned_short;
+static struct type *mdebug_type_unsigned_int_32;
+static struct type *mdebug_type_unsigned_int_64;
+static struct type *mdebug_type_unsigned_long_32;
+static struct type *mdebug_type_unsigned_long_64;
+static struct type *mdebug_type_unsigned_long_long_64;
+static struct type *mdebug_type_adr_32;
+static struct type *mdebug_type_adr_64;
+static struct type *mdebug_type_float;
+static struct type *mdebug_type_double;
static struct type *mdebug_type_complex;
static struct type *mdebug_type_double_complex;
static struct type *mdebug_type_fixed_dec;
static struct type *mdebug_type_float_dec;
static struct type *mdebug_type_string;
+/* Types for symbols from files compiled without debugging info. */
+
+static struct type *nodebug_func_symbol_type;
+static struct type *nodebug_var_symbol_type;
+
+/* Nonzero if we have seen ecoff debugging info for a file. */
+
+static int found_ecoff_debugging_info;
+
/* Forward declarations */
+static void
+add_pending PARAMS ((FDR *, char *, struct type *));
+
+static struct mdebug_pending *
+is_pending_symbol PARAMS ((FDR *, char *));
+
+static void
+pop_parse_stack PARAMS ((void));
+
+static void
+push_parse_stack PARAMS ((void));
+
+static char *
+fdr_name PARAMS ((FDR *));
+
+static void
+mdebug_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
static int
upgrade_type PARAMS ((int, struct type **, int, union aux_ext *, int, char *));
static FDR
*get_rfd PARAMS ((int, int));
+static int
+has_opaque_xref PARAMS ((FDR *, SYMR *));
+
static int
cross_ref PARAMS ((int, union aux_ext *, struct type **, enum type_code,
char **, int, char *));
new_bvect PARAMS ((int));
static int
-parse_symbol PARAMS ((SYMR *, union aux_ext *, char *, int));
+parse_symbol PARAMS ((SYMR *, union aux_ext *, char *, int, struct section_offsets *));
static struct type *
parse_type PARAMS ((int, union aux_ext *, unsigned int, int *, int, char *));
static struct symbol *
-mylookup_symbol PARAMS ((char *, struct block *, enum namespace,
+mylookup_symbol PARAMS ((char *, struct block *, namespace_enum,
enum address_class));
static struct block *
compare_blocks PARAMS ((const void *, const void *));
static struct partial_symtab *
-new_psymtab PARAMS ((char *, struct objfile *));
+new_psymtab PARAMS ((char *, struct objfile *, struct section_offsets *));
static void
psymtab_to_symtab_1 PARAMS ((struct partial_symtab *, char *));
static struct linetable *
shrink_linetable PARAMS ((struct linetable *));
+static void
+handle_psymbol_enumerators PARAMS ((struct objfile *, FDR *, int, CORE_ADDR));
+
static char *
-mdebug_next_symbol_text PARAMS ((void));
+mdebug_next_symbol_text PARAMS ((struct objfile *));
\f
/* Address bounds for the signal trampoline in inferior, if any */
SYMR's handled (normally one). */
static int
-parse_symbol (sh, ax, ext_sh, bigend)
+parse_symbol (sh, ax, ext_sh, bigend, section_offsets)
SYMR *sh;
union aux_ext *ax;
char *ext_sh;
int bigend;
+ struct section_offsets *section_offsets;
{
const bfd_size_type external_sym_size = debug_swap->external_sym_size;
void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) =
else
name = debug_info->ss + cur_fdr->issBase + sh->iss;
+ switch (sh->sc)
+ {
+ case scText:
+ case scRConst:
+ /* Do not relocate relative values.
+ The value of a stEnd symbol is the displacement from the
+ corresponding start symbol value.
+ The value of a stBlock symbol is the displacement from the
+ procedure address. */
+ if (sh->st != stEnd && sh->st != stBlock)
+ sh->value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ sh->value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ break;
+ case scBss:
+ case scSBss:
+ sh->value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ break;
+ }
+
switch (sh->st)
{
case stNil:
class = LOC_STATIC;
b = top_stack->cur_block;
s = new_symbol (name);
- if (sh->sc == scCommon)
+ if (SC_IS_COMMON(sh->sc))
{
/* It is a FORTRAN common block. At least for SGI Fortran the
address is not in the symbol; we need to fix it later in
SYMBOL_CLASS (s) = class;
add_symbol (s, b);
- /* Type could be missing in a number of cases */
- if (sh->sc == scUndefined || sh->sc == scNil ||
- sh->index == 0xfffff)
- SYMBOL_TYPE (s) = builtin_type_int; /* undefined? */
+ /* Type could be missing if file is compiled without debugging info. */
+ if (SC_IS_UNDEF(sh->sc)
+ || sh->sc == scNil || sh->index == indexNil)
+ SYMBOL_TYPE (s) = nodebug_var_symbol_type;
else
SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name);
/* Value of a data symbol is its memory address */
case stParam: /* arg to procedure, goes into current block */
max_gdbinfo++;
+ found_ecoff_debugging_info = 1;
top_stack->numargs++;
/* Special GNU C++ name. */
- if (name[0] == CPLUS_MARKER && name[1] == 't' && name[2] == 0)
+ if (is_cplus_marker (name[0]) && name[1] == 't' && name[2] == 0)
name = "this"; /* FIXME, not alloc'd in obstack */
s = new_symbol (name);
SYMBOL_VALUE (s) = svalue;
SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name);
add_symbol (s, top_stack->cur_block);
-#if 0
- /* FIXME: This has not been tested. See dbxread.c */
- /* Add the type of this parameter to the function/procedure
- type of this block. */
- add_param_to_type (&top_stack->cur_block->function->type, s);
-#endif
break;
case stLabel: /* label, goes into current block */
SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; /* so that it can be used */
SYMBOL_CLASS (s) = LOC_LABEL; /* but not misused */
SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value;
- SYMBOL_TYPE (s) = builtin_type_int;
+ SYMBOL_TYPE (s) = mdebug_type_int;
add_symbol (s, top_stack->cur_block);
break;
SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
SYMBOL_CLASS (s) = LOC_BLOCK;
/* Type of the return value */
- if (sh->sc == scUndefined || sh->sc == scNil)
- t = builtin_type_int;
+ if (SC_IS_UNDEF(sh->sc) || sh->sc == scNil)
+ t = mdebug_type_int;
else
- t = parse_type (cur_fd, ax, sh->index + 1, 0, bigend, name);
+ {
+ t = parse_type (cur_fd, ax, sh->index + 1, 0, bigend, name);
+ if (STREQ(name, "malloc") && t->code == TYPE_CODE_VOID)
+ {
+ /* I don't know why, but, at least under Alpha GNU/Linux,
+ when linking against a malloc without debugging
+ symbols, its read as a function returning void---this
+ is bad because it means we cannot call functions with
+ string arguments interactively; i.e., "call
+ printf("howdy\n")" would fail with the error message
+ "program has no memory available". To avoid this, we
+ patch up the type and make it void*
+ instead. (davidm@azstarnet.com)
+ */
+ t = make_pointer_type (t, NULL);
+ }
+ }
b = top_stack->cur_block;
if (sh->st == stProc)
{
add_symbol (s, b);
/* Make a type for the procedure itself */
-#if 0
- /* FIXME: This has not been tested yet! See dbxread.c */
- /* Generate a template for the type of this function. The
- types of the arguments will be added as we read the symbol
- table. */
- memcpy (lookup_function_type (t), SYMBOL_TYPE (s), sizeof (struct type));
-#else
SYMBOL_TYPE (s) = lookup_function_type (t);
-#endif
/* Create and enter a new lexical context */
b = new_block (top_stack->maxsyms);
add_block (b, top_stack->cur_st);
/* Not if we only have partial info */
- if (sh->sc == scUndefined || sh->sc == scNil)
+ if (SC_IS_UNDEF(sh->sc) || sh->sc == scNil)
break;
push_parse_stack ();
goto structured_common;
case stBlock: /* Either a lexical block, or some type */
- if (sh->sc != scInfo && sh->sc != scCommon)
+ if (sh->sc != scInfo && !SC_IS_COMMON(sh->sc))
goto case_stBlock_code; /* Lexical block */
type_code = TYPE_CODE_UNDEF; /* We have a type. */
unknown-type blocks of info about structured data. `type_code'
has been set to the proper TYPE_CODE, if we know it. */
structured_common:
+ found_ecoff_debugging_info = 1;
push_parse_stack ();
top_stack->blocktype = stBlock;
if (nfields == 0 && type_code == TYPE_CODE_UNDEF)
/* If the type of the member is Nil (or Void),
without qualifiers, assume the tag is an
- enumeration. */
- if (tsym.index == indexNil)
+ enumeration.
+ Alpha cc -migrate enums are recognized by a zero
+ index and a zero symbol value.
+ DU 4.0 cc enums are recognized by a member type of
+ btEnum without qualifiers and a zero symbol value. */
+ if (tsym.index == indexNil
+ || (tsym.index == 0 && sh->value == 0))
type_code = TYPE_CODE_ENUM;
else
{
- ecoff_swap_tir_in (bigend,
- &ax[tsym.index].a_ti,
- &tir);
- if ((tir.bt == btNil || tir.bt == btVoid)
+ (*debug_swap->swap_tir_in) (bigend,
+ &ax[tsym.index].a_ti,
+ &tir);
+ if ((tir.bt == btNil || tir.bt == btVoid
+ || (tir.bt == btEnum && sh->value == 0))
&& tir.tq0 == tqNil)
type_code = TYPE_CODE_ENUM;
}
Just ignore it. */
break;
+ case stIndirect:
+ /* Irix5 cc puts out a stIndirect for struct x if it is not
+ yet defined when it encounters
+ struct y { struct x *xp; };
+ Just ignore it. */
+ break;
+
default:
complain (&block_member_complaint, tsym.st);
}
if (type_code == TYPE_CODE_ENUM)
{
+ int unsigned_enum = 1;
+
/* This is a non-empty enum. */
/* DEC c89 has the number of enumerators in the sh.value field,
incompatibility quirk.
This might do the wrong thing for an enum with one or two
enumerators and gcc -gcoff -fshort-enums, but these cases
- are hopefully rare enough. */
- if (TYPE_LENGTH (t) == TYPE_NFIELDS (t))
+ are hopefully rare enough.
+ Alpha cc -migrate has a sh.value field of zero, we adjust
+ that too. */
+ if (TYPE_LENGTH (t) == TYPE_NFIELDS (t)
+ || TYPE_LENGTH (t) == 0)
TYPE_LENGTH (t) = TARGET_INT_BIT / HOST_CHAR_BIT;
for (ext_tsym = ext_sh + external_sym_size;
;
if (tsym.st != stMember)
break;
- f->bitpos = tsym.value;
- f->type = t;
- f->name = debug_info->ss + cur_fdr->issBase + tsym.iss;
- f->bitsize = 0;
+ FIELD_BITPOS (*f) = tsym.value;
+ FIELD_TYPE (*f) = t;
+ FIELD_NAME (*f) = debug_info->ss + cur_fdr->issBase + tsym.iss;
+ FIELD_BITSIZE (*f) = 0;
enum_sym = ((struct symbol *)
obstack_alloc (¤t_objfile->symbol_obstack,
sizeof (struct symbol)));
memset ((PTR) enum_sym, 0, sizeof (struct symbol));
- SYMBOL_NAME (enum_sym) = f->name;
+ SYMBOL_NAME (enum_sym) =
+ obsavestring (f->name, strlen (f->name),
+ ¤t_objfile->symbol_obstack);
SYMBOL_CLASS (enum_sym) = LOC_CONST;
SYMBOL_TYPE (enum_sym) = t;
SYMBOL_NAMESPACE (enum_sym) = VAR_NAMESPACE;
SYMBOL_VALUE (enum_sym) = tsym.value;
+ if (SYMBOL_VALUE (enum_sym) < 0)
+ unsigned_enum = 0;
add_symbol (enum_sym, top_stack->cur_block);
/* Skip the stMembers that we've handled. */
count++;
f++;
}
+ if (unsigned_enum)
+ TYPE_FLAGS (t) |= TYPE_FLAG_UNSIGNED;
}
/* make this the current type */
top_stack->cur_type = t;
}
case_stBlock_code:
+ found_ecoff_debugging_info = 1;
/* beginnning of (code) block. Value of symbol
is the displacement from procedure start */
push_parse_stack ();
break;
case stEnd: /* end (of anything) */
- if (sh->sc == scInfo || sh->sc == scCommon)
+ if (sh->sc == scInfo || SC_IS_COMMON(sh->sc))
{
/* Finished with type */
top_stack->cur_type = 0;
struct blockvector *bv = BLOCKVECTOR (top_stack->cur_st);
struct mips_extra_func_info *e;
struct block *b;
+ struct type *ftype = top_stack->cur_type;
int i;
BLOCK_END (top_stack->cur_block) += sh->value; /* size */
s = new_symbol (MIPS_EFI_SYMBOL_NAME);
SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
SYMBOL_CLASS (s) = LOC_CONST;
- SYMBOL_TYPE (s) = builtin_type_void;
+ SYMBOL_TYPE (s) = mdebug_type_void;
e = ((struct mips_extra_func_info *)
obstack_alloc (¤t_objfile->symbol_obstack,
sizeof (struct mips_extra_func_info)));
+ memset ((PTR) e, 0, sizeof (struct mips_extra_func_info));
SYMBOL_VALUE (s) = (long) e;
e->numargs = top_stack->numargs;
+ e->pdr.framereg = -1;
add_symbol (s, top_stack->cur_block);
/* Reallocate symbols, saving memory */
BLOCK_END (b_bad) = BLOCK_END (b);
}
}
+
+ if (TYPE_NFIELDS (ftype) <= 0)
+ {
+ /* No parameter type information is recorded with the function's
+ type. Set that from the type of the parameter symbols. */
+ int nparams = top_stack->numargs;
+ int iparams;
+ struct symbol *sym;
+
+ if (nparams > 0)
+ {
+ TYPE_NFIELDS (ftype) = nparams;
+ TYPE_FIELDS (ftype) = (struct field *)
+ TYPE_ALLOC (ftype, nparams * sizeof (struct field));
+
+ for (i = iparams = 0; iparams < nparams; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
+ iparams++;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
}
else if (sh->sc == scText && top_stack->blocktype == stBlock)
{
case stMember: /* member of struct or union */
f = &TYPE_FIELDS (top_stack->cur_type)[top_stack->cur_field++];
- f->name = name;
- f->bitpos = sh->value;
+ FIELD_NAME (*f) = name;
+ FIELD_BITPOS (*f) = sh->value;
bitsize = 0;
- f->type = parse_type (cur_fd, ax, sh->index, &bitsize, bigend, name);
- f->bitsize = bitsize;
+ FIELD_TYPE (*f) = parse_type (cur_fd, ax, sh->index, &bitsize, bigend, name);
+ FIELD_BITSIZE (*f) = bitsize;
+ break;
+
+ case stIndirect: /* forward declaration on Irix5 */
+ /* Forward declarations from Irix5 cc are handled by cross_ref,
+ skip them. */
break;
case stTypedef: /* type definition */
+ found_ecoff_debugging_info = 1;
+
/* Typedefs for forward declarations and opaque structs from alpha cc
are handled by cross_ref, skip them. */
if (sh->iss == 0)
generates a cross referencing stTypedef for x and xx.
The user visible effect of this is that the type of a pointer
to struct foo sometimes is given as `foo *' instead of `struct foo *'.
- The problem is fixed with alpha cc. */
+ The problem is fixed with alpha cc and Irix5 cc. */
+
+ /* However if the typedef cross references to an opaque aggregate, it
+ is safe to omit it from the symbol table. */
+ if (has_opaque_xref (cur_fdr, sh))
+ break;
s = new_symbol (name);
SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
SYMBOL_CLASS (s) = LOC_TYPEDEF;
/* Null entries in this map are treated specially */
static struct type **map_bt[] =
{
- &builtin_type_void, /* btNil */
- 0, /* btAdr */
- &builtin_type_char, /* btChar */
- &builtin_type_unsigned_char,/* btUChar */
- &builtin_type_short, /* btShort */
- &builtin_type_unsigned_short, /* btUShort */
- &builtin_type_int, /* btInt */
- &builtin_type_unsigned_int, /* btUInt */
- &builtin_type_long, /* btLong */
- &builtin_type_unsigned_long,/* btULong */
- &builtin_type_float, /* btFloat */
- &builtin_type_double, /* btDouble */
- 0, /* btStruct */
- 0, /* btUnion */
- 0, /* btEnum */
- 0, /* btTypedef */
- 0, /* btRange */
- 0, /* btSet */
- &mdebug_type_complex, /* btComplex */
+ &mdebug_type_void, /* btNil */
+ &mdebug_type_adr_32, /* btAdr */
+ &mdebug_type_char, /* btChar */
+ &mdebug_type_unsigned_char, /* btUChar */
+ &mdebug_type_short, /* btShort */
+ &mdebug_type_unsigned_short, /* btUShort */
+ &mdebug_type_int_32, /* btInt */
+ &mdebug_type_unsigned_int_32, /* btUInt */
+ &mdebug_type_long_32, /* btLong */
+ &mdebug_type_unsigned_long_32, /* btULong */
+ &mdebug_type_float, /* btFloat */
+ &mdebug_type_double, /* btDouble */
+ 0, /* btStruct */
+ 0, /* btUnion */
+ 0, /* btEnum */
+ 0, /* btTypedef */
+ 0, /* btRange */
+ 0, /* btSet */
+ &mdebug_type_complex, /* btComplex */
&mdebug_type_double_complex, /* btDComplex */
- 0, /* btIndirect */
- &mdebug_type_fixed_dec, /* btFixedDec */
- &mdebug_type_float_dec, /* btFloatDec */
- &mdebug_type_string, /* btString */
- 0, /* btBit */
- 0, /* btPicture */
- &builtin_type_void, /* btVoid */
- 0, /* DEC C++: Pointer to member */
- 0, /* DEC C++: Virtual function table */
- 0, /* DEC C++: Class (Record) */
- &builtin_type_long, /* btLong64 */
- &builtin_type_unsigned_long, /* btULong64 */
- &builtin_type_long_long, /* btLongLong64 */
- &builtin_type_unsigned_long_long, /* btULongLong64 */
- &builtin_type_unsigned_long, /* btAdr64 */
- &builtin_type_long, /* btInt64 */
- &builtin_type_unsigned_long, /* btUInt64 */
+ 0, /* btIndirect */
+ &mdebug_type_fixed_dec, /* btFixedDec */
+ &mdebug_type_float_dec, /* btFloatDec */
+ &mdebug_type_string, /* btString */
+ 0, /* btBit */
+ 0, /* btPicture */
+ &mdebug_type_void, /* btVoid */
+ 0, /* DEC C++: Pointer to member */
+ 0, /* DEC C++: Virtual function table */
+ 0, /* DEC C++: Class (Record) */
+ &mdebug_type_long_64, /* btLong64 */
+ &mdebug_type_unsigned_long_64, /* btULong64 */
+ &mdebug_type_long_long_64, /* btLongLong64 */
+ &mdebug_type_unsigned_long_long_64, /* btULongLong64 */
+ &mdebug_type_adr_64, /* btAdr64 */
+ &mdebug_type_int_64, /* btInt64 */
+ &mdebug_type_unsigned_int_64, /* btUInt64 */
};
TIR t[1];
struct type *tp = 0;
enum type_code type_code = TYPE_CODE_UNDEF;
+ /* Handle undefined types, they have indexNil. */
+ if (aux_index == indexNil)
+ return mdebug_type_int;
+
/* Handle corrupt aux indices. */
if (aux_index >= (debug_info->fdr + fd)->caux)
{
complain (&index_complaint, sym_name);
- return builtin_type_int;
+ return mdebug_type_int;
}
ax += aux_index;
/* Use aux as a type information record, map its basic type. */
- ecoff_swap_tir_in (bigend, &ax->a_ti, t);
+ (*debug_swap->swap_tir_in) (bigend, &ax->a_ti, t);
if (t->bt >= (sizeof (map_bt) / sizeof (*map_bt)))
{
complain (&basic_type_complaint, t->bt, sym_name);
- return builtin_type_int;
+ return mdebug_type_int;
}
if (map_bt[t->bt])
{
/* Cannot use builtin types -- build our own */
switch (t->bt)
{
- case btAdr:
- tp = lookup_pointer_type (builtin_type_void);
- break;
case btStruct:
type_code = TYPE_CODE_STRUCT;
break;
case btSet:
type_code = TYPE_CODE_SET;
break;
+ case btIndirect:
+ /* alpha cc -migrate uses this for typedefs. The true type will
+ be obtained by crossreferencing below. */
+ type_code = TYPE_CODE_ERROR;
+ break;
case btTypedef:
/* alpha cc uses this for typedefs. The true type will be
obtained by crossreferencing below. */
break;
default:
complain (&basic_type_complaint, t->bt, sym_name);
- return builtin_type_int;
+ return mdebug_type_int;
}
}
if (t->fBitfield)
{
+ int width = AUX_GET_WIDTH (bigend, ax);
+
/* Inhibit core dumps with some cfront generated objects that
corrupt the TIR. */
if (bs == (int *)NULL)
{
- complain (&bad_fbitfield_complaint, sym_name);
- return builtin_type_int;
+ /* Alpha cc -migrate encodes char and unsigned char types
+ as short and unsigned short types with a field width of 8.
+ Enum types also have a field width which we ignore for now. */
+ if (t->bt == btShort && width == 8)
+ tp = mdebug_type_char;
+ else if (t->bt == btUShort && width == 8)
+ tp = mdebug_type_unsigned_char;
+ else if (t->bt == btEnum)
+ ;
+ else
+ complain (&bad_fbitfield_complaint, sym_name);
}
- *bs = AUX_GET_WIDTH (bigend, ax);
+ else
+ *bs = width;
+ ax++;
+ }
+
+ /* A btIndirect entry cross references to an aux entry containing
+ the type. */
+ if (t->bt == btIndirect)
+ {
+ RNDXR rn[1];
+ int rf;
+ FDR *xref_fh;
+ int xref_fd;
+
+ (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, rn);
ax++;
+ if (rn->rfd == 0xfff)
+ {
+ rf = AUX_GET_ISYM (bigend, ax);
+ ax++;
+ }
+ else
+ rf = rn->rfd;
+
+ if (rf == -1)
+ {
+ complain (&bad_indirect_xref_complaint, sym_name);
+ return mdebug_type_int;
+ }
+ xref_fh = get_rfd (fd, rf);
+ xref_fd = xref_fh - debug_info->fdr;
+ tp = parse_type (xref_fd, debug_info->external_aux + xref_fh->iauxBase,
+ rn->index, (int *) NULL, xref_fh->fBigendian, sym_name);
}
/* All these types really point to some (common) MIPS type
/* All these types really point to some (common) MIPS type
definition, and only the type-qualifiers fully identify
them. We'll make the same effort at sharing.
- FIXME: btIndirect cannot happen here as it is handled by the
- switch t->bt above. And we are not doing any guessing on range types. */
- if (t->bt == btIndirect ||
- t->bt == btRange)
+ FIXME: We are not doing any guessing on range types. */
+ if (t->bt == btRange)
{
char *name;
if (tp == (struct type *) NULL)
{
complain (&unable_to_cross_ref_complaint, sym_name);
- tp = builtin_type_int;
+ tp = mdebug_type_int;
}
}
if (!t->continued)
break;
- ecoff_swap_tir_in (bigend, &ax->a_ti, t);
+ (*debug_swap->swap_tir_in) (bigend, &ax->a_ti, t);
ax++;
}
off = 0;
/* Determine and record the domain type (type of index) */
- ecoff_swap_rndx_in (bigend, &ax->a_rndx, &rndx);
+ (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, &rndx);
id = rndx.index;
rf = rndx.rfd;
if (rf == 0xfff)
}
fh = get_rfd (fd, rf);
- indx = parse_type (fd, debug_info->external_aux + fh->iauxBase,
+ indx = parse_type (fh - debug_info->fdr,
+ debug_info->external_aux + fh->iauxBase,
id, (int *) NULL, bigend, sym_name);
/* The bounds type should be an integer type, but might be anything
if (TYPE_CODE (indx) != TYPE_CODE_INT)
{
complain (&array_index_type_complaint, sym_name);
- indx = builtin_type_int;
+ indx = mdebug_type_int;
}
/* Get the bounds, and create the array type. */
ignore the erroneous bitsize from the auxiliary entry safely.
dbx seems to ignore it too. */
+ /* TYPE_FLAG_TARGET_STUB now takes care of the zero TYPE_LENGTH
+ problem. */
+ if (TYPE_LENGTH (*tpp) == 0)
+ {
+ TYPE_FLAGS (t) |= TYPE_FLAG_TARGET_STUB;
+ }
+
*tpp = t;
return 4 + off;
to look for the function which contains the MIPS_EFI_SYMBOL_NAME symbol
in question, or NULL to use top_stack->cur_block. */
-static void parse_procedure PARAMS ((PDR *, struct symtab *, unsigned long));
+static void parse_procedure PARAMS ((PDR *, struct symtab *,
+ struct partial_symtab *));
static void
-parse_procedure (pr, search_symtab, first_off)
+parse_procedure (pr, search_symtab, pst)
PDR *pr;
struct symtab *search_symtab;
- unsigned long first_off;
+ struct partial_symtab *pst;
{
struct symbol *s, *i;
struct block *b;
SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
SYMBOL_CLASS (s) = LOC_BLOCK;
/* Donno its type, hope int is ok */
- SYMBOL_TYPE (s) = lookup_function_type (builtin_type_int);
+ SYMBOL_TYPE (s) = lookup_function_type (mdebug_type_int);
add_symbol (s, top_stack->cur_block);
/* Wont have symbols for this one */
b = new_block (2);
e = (struct mips_extra_func_info *) SYMBOL_VALUE (i);
e->pdr = *pr;
e->pdr.isym = (long) s;
- e->pdr.adr += cur_fdr->adr - first_off;
+
+ /* GDB expects the absolute function start address for the
+ procedure descriptor in e->pdr.adr.
+ As the address in the procedure descriptor is usually relative,
+ we would have to relocate e->pdr.adr with cur_fdr->adr and
+ ANOFFSET (pst->section_offsets, SECT_OFF_TEXT).
+ Unfortunately cur_fdr->adr and e->pdr.adr are both absolute
+ in shared libraries on some systems, and on other systems
+ e->pdr.adr is sometimes offset by a bogus value.
+ To work around these problems, we replace e->pdr.adr with
+ the start address of the function. */
+ e->pdr.adr = BLOCK_START (b);
/* Correct incorrect setjmp procedure descriptor from the library
to make backtrace through setjmp work. */
e->pdr.regoffset = -4;
}
}
+
+ /* It would be reasonable that functions that have been compiled
+ without debugging info have a btNil type for their return value,
+ and functions that are void and are compiled with debugging info
+ have btVoid.
+ gcc and DEC f77 put out btNil types for both cases, so btNil is mapped
+ to TYPE_CODE_VOID in parse_type to get the `compiled with debugging info'
+ case right.
+ The glevel field in cur_fdr could be used to determine the presence
+ of debugging info, but GCC doesn't always pass the -g switch settings
+ to the assembler and GAS doesn't set the glevel field from the -g switch
+ settings.
+ To work around these problems, the return value type of a TYPE_CODE_VOID
+ function is adjusted accordingly if no debugging info was found in the
+ compilation unit. */
+
+ if (processing_gcc_compilation == 0
+ && found_ecoff_debugging_info == 0
+ && TYPE_CODE (TYPE_TARGET_TYPE (SYMBOL_TYPE (s))) == TYPE_CODE_VOID)
+ SYMBOL_TYPE (s) = nodebug_func_symbol_type;
+}
+
+/* Relocate the extra function info pointed to by the symbol table. */
+
+void
+ecoff_relocate_efi (sym, delta)
+ struct symbol *sym;
+ CORE_ADDR delta;
+{
+ struct mips_extra_func_info *e;
+
+ e = (struct mips_extra_func_info *) SYMBOL_VALUE (sym);
+
+ e->pdr.adr += delta;
}
/* Parse the external symbol ES. Just call parse_symbol() after
- making sure we know where the aux are for it. For procedures,
- parsing of the PDRs has already provided all the needed
- information, we only parse them if SKIP_PROCEDURES is false,
- and only if this causes no symbol duplication.
+ making sure we know where the aux are for it.
BIGEND says whether aux entries are big-endian or little-endian.
This routine clobbers top_stack->cur_block and ->cur_st. */
+static void parse_external PARAMS ((EXTR *, int, struct section_offsets *));
+
static void
-parse_external (es, skip_procedures, bigend)
+parse_external (es, bigend, section_offsets)
EXTR *es;
- int skip_procedures;
int bigend;
+ struct section_offsets *section_offsets;
{
union aux_ext *ax;
}
/* Reading .o files */
- if (es->asym.sc == scUndefined || es->asym.sc == scNil)
+ if (SC_IS_UNDEF(es->asym.sc) || es->asym.sc == scNil)
{
char *what;
switch (es->asym.st)
switch (es->asym.st)
{
case stProc:
- /* If we have full symbols we do not need more */
- if (skip_procedures)
- return;
- if (mylookup_symbol (debug_info->ssext + es->asym.iss,
- top_stack->cur_block,
- VAR_NAMESPACE, LOC_BLOCK))
- break;
- /* fall through */
+ case stStaticProc:
+ /* There is no need to parse the external procedure symbols.
+ If they are from objects compiled without -g, their index will
+ be indexNil, and the symbol definition from the minimal symbol
+ is preferrable (yielding a function returning int instead of int).
+ If the index points to a local procedure symbol, the local
+ symbol already provides the correct type.
+ Note that the index of the external procedure symbol points
+ to the local procedure symbol in the local symbol table, and
+ _not_ to the auxiliary symbol info. */
+ break;
case stGlobal:
case stLabel:
+ /* Global common symbols are resolved by the runtime loader,
+ ignore them. */
+ if (SC_IS_COMMON(es->asym.sc))
+ break;
+
/* Note that the case of a symbol with indexNil must be handled
anyways by parse_symbol(). */
- parse_symbol (&es->asym, ax, (char *) NULL, bigend);
+ parse_symbol (&es->asym, ax, (char *) NULL, bigend, section_offsets);
break;
default:
break;
numbers can go back and forth, apparently we can live
with that and do not need to reorder our linetables */
+static void parse_lines PARAMS ((FDR *, PDR *, struct linetable *, int,
+ struct partial_symtab *, CORE_ADDR));
+
static void
-parse_lines (fh, pr, lt, maxlines)
+parse_lines (fh, pr, lt, maxlines, pst, lowest_pdr_addr)
FDR *fh;
PDR *pr;
struct linetable *lt;
int maxlines;
+ struct partial_symtab *pst;
+ CORE_ADDR lowest_pdr_addr;
{
unsigned char *base;
int j, k;
int delta, count, lineno = 0;
- unsigned long first_off = pr->adr;
if (fh->cbLine == 0)
return;
- base = debug_info->line + fh->cbLineOffset;
-
/* Scan by procedure descriptors */
k = 0;
for (j = 0; j < fh->cpd; j++, pr++)
{
- long l;
- unsigned long adr;
+ CORE_ADDR l;
+ CORE_ADDR adr;
unsigned char *halt;
/* No code for this one */
halt = base + fh->cbLine;
base += pr->cbLineOffset;
- adr = fh->adr + pr->adr - first_off;
+ adr = pst->textlow + pr->adr - lowest_pdr_addr;
+
l = adr >> 2; /* in words */
for (lineno = pr->lnLow; base < halt; )
{
EXTR *ext_in_end;
SYMR sh;
struct partial_symtab *pst;
-
+ int textlow_not_set = 1;
int past_first_source_file = 0;
/* List of current psymtab's include files */
struct cleanup *old_chain;
char *name;
enum language prev_language;
+ asection *text_sect;
+ int relocatable = 0;
+
+ /* Irix 5.2 shared libraries have a fh->adr field of zero, but
+ the shared libraries are prelinked at a high memory address.
+ We have to adjust the start address of the object file for this case,
+ by setting it to the start address of the first procedure in the file.
+ But we should do no adjustments if we are debugging a .o file, where
+ the text section (and fh->adr) really starts at zero. */
+ text_sect = bfd_get_section_by_name (cur_bfd, ".text");
+ if (text_sect != NULL
+ && (bfd_get_section_flags (cur_bfd, text_sect) & SEC_RELOC))
+ relocatable = 1;
extern_tab = (EXTR *) obstack_alloc (&objfile->psymbol_obstack,
sizeof (EXTR) * hdr->iextMax);
old_chain = make_cleanup (free, fdr_to_pst);
fdr_to_pst++;
{
- struct partial_symtab *pst = new_psymtab ("", objfile);
+ struct partial_symtab *pst = new_psymtab ("", objfile, section_offsets);
fdr_to_pst[-1].pst = pst;
FDR_IDX (pst) = -1;
}
fdr_to_pst[f_idx].n_globals = 0;
}
- /* Pass 2 over external syms: fill in external symbols */
- ext_in = ext_block;
- ext_in_end = ext_in + hdr->iextMax;
- for (; ext_in < ext_in_end; ext_in++)
- {
- enum minimal_symbol_type ms_type = mst_text;
+ /* ECOFF in ELF:
+
+ For ECOFF in ELF, we skip the creation of the minimal symbols.
+ The ECOFF symbols should be a subset of the Elf symbols, and the
+ section information of the elf symbols will be more accurate.
+ FIXME! What about Irix 5's native linker?
+
+ By default, Elf sections which don't exist in ECOFF
+ get put in ECOFF's absolute section by the gnu linker.
+ Since absolute sections don't get relocated, we
+ end up calculating an address different from that of
+ the symbol's minimal symbol (created earlier from the
+ Elf symtab).
+
+ To fix this, either :
+ 1) don't create the duplicate symbol
+ (assumes ECOFF symtab is a subset of the ELF symtab;
+ assumes no side-effects result from ignoring ECOFF symbol)
+ 2) create it, only if lookup for existing symbol in ELF's minimal
+ symbols fails
+ (inefficient;
+ assumes no side-effects result from ignoring ECOFF symbol)
+ 3) create it, but lookup ELF's minimal symbol and use it's section
+ during relocation, then modify "uniqify" phase to merge and
+ eliminate the duplicate symbol
+ (highly inefficient)
+
+ I've implemented #1 here...
+ Skip the creation of the minimal symbols based on the ECOFF
+ symbol table. */
+
+ /* Pass 2 over external syms: fill in external symbols */
+ ext_in = ext_block;
+ ext_in_end = ext_in + hdr->iextMax;
+ for (; ext_in < ext_in_end; ext_in++)
+ {
+ enum minimal_symbol_type ms_type = mst_text;
+ CORE_ADDR svalue = ext_in->asym.value;
- /* The Irix 5 native tools seem to sometimes generate bogus
- external symbols. */
- if (ext_in->ifd < -1 || ext_in->ifd >= hdr->ifdMax)
- {
- complain (&bad_ext_ifd_complaint, ext_in->ifd, hdr->ifdMax);
- continue;
- }
- if (ext_in->asym.iss < 0 || ext_in->asym.iss >= hdr->issExtMax)
- {
- complain (&bad_ext_iss_complaint, ext_in->asym.iss,
- hdr->issExtMax);
- continue;
- }
+ /* The Irix 5 native tools seem to sometimes generate bogus
+ external symbols. */
+ if (ext_in->ifd < -1 || ext_in->ifd >= hdr->ifdMax)
+ {
+ complain (&bad_ext_ifd_complaint, ext_in->ifd, hdr->ifdMax);
+ continue;
+ }
+ if (ext_in->asym.iss < 0 || ext_in->asym.iss >= hdr->issExtMax)
+ {
+ complain (&bad_ext_iss_complaint, ext_in->asym.iss,
+ hdr->issExtMax);
+ continue;
+ }
- extern_tab[fdr_to_pst[ext_in->ifd].globals_offset
- + fdr_to_pst[ext_in->ifd].n_globals++] = *ext_in;
+ extern_tab[fdr_to_pst[ext_in->ifd].globals_offset
+ + fdr_to_pst[ext_in->ifd].n_globals++] = *ext_in;
- if (ext_in->asym.sc == scUndefined || ext_in->asym.sc == scNil)
- continue;
- name = debug_info->ssext + ext_in->asym.iss;
- switch (ext_in->asym.st)
- {
- case stProc:
- break;
- case stStaticProc:
- ms_type = mst_file_text;
- break;
- case stGlobal:
- if (ext_in->asym.sc == scData
- || ext_in->asym.sc == scSData
- || ext_in->asym.sc == scRData)
- ms_type = mst_data;
- else
- ms_type = mst_bss;
- break;
- case stLabel:
- if (ext_in->asym.sc == scAbs)
- ms_type = mst_abs;
- else if (ext_in->asym.sc == scText)
- ms_type = mst_text;
- else if (ext_in->asym.sc == scData
- || ext_in->asym.sc == scSData
- || ext_in->asym.sc == scRData)
- ms_type = mst_data;
- else
- ms_type = mst_bss;
- break;
- case stLocal:
- /* The alpha has the section start addresses in stLocal symbols
- whose name starts with a `.'. Skip those but complain for all
- other stLocal symbols. */
- if (name[0] == '.')
- continue;
- /* Fall through. */
- default:
- ms_type = mst_unknown;
- complain (&unknown_ext_complaint, name);
- }
- prim_record_minimal_symbol (name, ext_in->asym.value, ms_type, objfile);
- }
+ if (SC_IS_UNDEF(ext_in->asym.sc) || ext_in->asym.sc == scNil)
+ continue;
+
+
+ /* Pass 3 over files, over local syms: fill in static symbols */
+ name = debug_info->ssext + ext_in->asym.iss;
+
+ /* Process ECOFF Symbol Types and Storage Classes */
+ switch (ext_in->asym.st)
+ {
+ case stProc:
+ /* Beginnning of Procedure */
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case stStaticProc:
+ /* Load time only static procs */
+ ms_type = mst_file_text;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case stGlobal:
+ /* External symbol */
+ if (SC_IS_COMMON (ext_in->asym.sc))
+ {
+ /* The value of a common symbol is its size, not its address.
+ Ignore it. */
+ continue;
+ }
+ else if (SC_IS_DATA (ext_in->asym.sc))
+ {
+ ms_type = mst_data;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ }
+ else if (SC_IS_BSS (ext_in->asym.sc))
+ {
+ ms_type = mst_bss;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ }
+ else
+ ms_type = mst_abs;
+ break;
+ case stLabel:
+ /* Label */
+ if (SC_IS_TEXT (ext_in->asym.sc))
+ {
+ ms_type = mst_file_text;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ }
+ else if (SC_IS_DATA (ext_in->asym.sc))
+ {
+ ms_type = mst_file_data;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ }
+ else if (SC_IS_BSS (ext_in->asym.sc))
+ {
+ ms_type = mst_file_bss;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ }
+ else
+ ms_type = mst_abs;
+ break;
+ case stLocal:
+ case stNil:
+ /* The alpha has the section start addresses in stLocal symbols
+ whose name starts with a `.'. Skip those but complain for all
+ other stLocal symbols.
+ Irix6 puts the section start addresses in stNil symbols, skip
+ those too.*/
+ if (name[0] == '.')
+ continue;
+ /* Fall through. */
+ default:
+ ms_type = mst_unknown;
+ complain (&unknown_ext_complaint, name);
+ }
+ if (!ECOFF_IN_ELF(cur_bfd))
+ prim_record_minimal_symbol (name, svalue, ms_type, objfile);
+ }
/* Pass 3 over files, over local syms: fill in static symbols */
for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++)
{
struct partial_symtab *save_pst;
EXTR *ext_ptr;
+ CORE_ADDR textlow;
cur_fdr = fh = debug_info->fdr + f_idx;
fdr_to_pst[f_idx].pst = NULL;
continue;
}
+
+ /* Determine the start address for this object file from the
+ file header and relocate it, except for Irix 5.2 zero fh->adr. */
+ if (fh->cpd)
+ {
+ textlow = fh->adr;
+ if (relocatable || textlow != 0)
+ textlow += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ }
+ else
+ textlow = 0;
pst = start_psymtab_common (objfile, section_offsets,
fdr_name (fh),
- fh->cpd ? fh->adr : 0,
+ textlow,
objfile->global_psymbols.next,
objfile->static_psymbols.next);
pst->read_symtab_private = ((char *)
{
if (sh.st == stProc || sh.st == stStaticProc)
{
- long procaddr = sh.value;
+ CORE_ADDR procaddr;
long isym;
-
+
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ if (sh.st == stStaticProc)
+ {
+ namestring = debug_info->ss + fh->issBase + sh.iss;
+ prim_record_minimal_symbol_and_info (namestring,
+ sh.value,
+ mst_file_text,
+ NULL,
+ SECT_OFF_TEXT,
+ NULL,
+ objfile);
+ }
+ procaddr = sh.value;
isym = AUX_GET_ISYM (fh->fBigendian,
(debug_info->external_aux
&sh);
if (sh.st == stEnd)
{
- long high = procaddr + sh.value;
+ CORE_ADDR high = procaddr + sh.value;
+
+ /* Kludge for Irix 5.2 zero fh->adr. */
+ if (!relocatable
+ && (pst->textlow == 0 || procaddr < pst->textlow))
+ pst->textlow = procaddr;
if (high > pst->texthigh)
pst->texthigh = high;
}
}
+ else if (sh.st == stStatic)
+ {
+ switch (sh.sc)
+ {
+ case scUndefined:
+ case scSUndefined:
+ case scNil:
+ case scAbs:
+ break;
+
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ namestring = debug_info->ss + fh->issBase + sh.iss;
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ prim_record_minimal_symbol_and_info (namestring,
+ sh.value,
+ mst_file_data,
+ NULL,
+ SECT_OFF_DATA,
+ NULL,
+ objfile);
+ break;
+
+ default:
+ /* FIXME! Shouldn't this use cases for bss,
+ then have the default be abs? */
+ namestring = debug_info->ss + fh->issBase + sh.iss;
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ prim_record_minimal_symbol_and_info (namestring,
+ sh.value,
+ mst_file_bss,
+ NULL,
+ SECT_OFF_BSS,
+ NULL,
+ objfile);
+ break;
+ }
+ }
continue;
}
+ /* Handle stabs continuation */
+ {
+ char *stabstring = debug_info->ss + fh->issBase + sh.iss;
+ int len = strlen (stabstring);
+ while (stabstring[len-1] == '\\')
+ {
+ SYMR sh2;
+ char *stabstring1 = stabstring;
+ char *stabstring2;
+ int len2;
+
+ /* Ignore continuation char from 1st string */
+ len--;
+
+ /* Read next stabstring */
+ cur_sdx++;
+ (*swap_sym_in) (cur_bfd,
+ (((char *) debug_info->external_sym)
+ + (fh->isymBase + cur_sdx)
+ * external_sym_size),
+ &sh2);
+ stabstring2 = debug_info->ss + fh->issBase + sh2.iss;
+ len2 = strlen (stabstring2);
+
+ /* Concatinate stabstring2 with stabstring1 */
+ if (stabstring
+ && stabstring != debug_info->ss + fh->issBase + sh.iss)
+ stabstring = xrealloc (stabstring, len + len2 + 1);
+ else
+ stabstring = xmalloc (len + len2 + 1);
+ strcpy (stabstring, stabstring1);
+ strcpy (stabstring + len, stabstring2);
+ len += len2;
+ }
+
#define SET_NAMESTRING() \
- namestring = debug_info->ss + fh->issBase + sh.iss
+ namestring = stabstring
#define CUR_SYMBOL_TYPE type_code
#define CUR_SYMBOL_VALUE sh.value
#define START_PSYMTAB(ofile,secoff,fname,low,symoff,global_syms,static_syms)\
pst = save_pst
-#define END_PSYMTAB(pst,ilist,ninc,c_off,c_text,dep_list,n_deps) (void)0
+#define END_PSYMTAB(pst,ilist,ninc,c_off,c_text,dep_list,n_deps,textlow_not_set) (void)0
#define HANDLE_RBRAC(val) \
if ((val) > save_pst->texthigh) save_pst->texthigh = (val);
#include "partial-stab.h"
+
+ if (stabstring
+ && stabstring != debug_info->ss + fh->issBase + sh.iss)
+ free (stabstring);
+ }
+ /* end - Handle continuation */
}
}
else
}
/* Non absolute static symbols go into the minimal table. */
- if (sh.sc == scUndefined || sh.sc == scNil
+ if (SC_IS_UNDEF(sh.sc) || sh.sc == scNil
|| (sh.index == indexNil
&& (sh.st != stStatic || sh.sc == scAbs)))
{
name = debug_info->ss + fh->issBase + sh.iss;
+ switch (sh.sc)
+ {
+ case scText:
+ case scRConst:
+ /* The value of a stEnd symbol is the displacement from the
+ corresponding start symbol value, do not relocate it. */
+ if (sh.st != stEnd)
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ break;
+ case scBss:
+ case scSBss:
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ break;
+ }
+
switch (sh.st)
{
- long high;
- long procaddr;
+ CORE_ADDR high;
+ CORE_ADDR procaddr;
int new_sdx;
- case stStaticProc: /* Function */
- /* I believe this is used only for file-local functions.
- The comment in symconst.h ("load time only static procs")
- isn't particularly clear on this point. */
- prim_record_minimal_symbol (name, sh.value, mst_file_text,
- objfile);
+ case stStaticProc:
+ prim_record_minimal_symbol_and_info (name, sh.value,
+ mst_file_text, NULL,
+ SECT_OFF_TEXT, NULL,
+ objfile);
+
/* FALLTHROUGH */
- case stProc: /* Asm labels apparently */
- ADD_PSYMBOL_TO_LIST (name, strlen (name),
- VAR_NAMESPACE, LOC_BLOCK,
- objfile->static_psymbols, sh.value,
- psymtab_language, objfile);
+ case stProc:
+ /* Usually there is a local and a global stProc symbol
+ for a function. This means that the function name
+ has already been entered into the mimimal symbol table
+ while processing the global symbols in pass 2 above.
+ One notable exception is the PROGRAM name from
+ f77 compiled executables, it is only put out as
+ local stProc symbol, and a global MAIN__ stProc symbol
+ points to it. It doesn't matter though, as gdb is
+ still able to find the PROGRAM name via the partial
+ symbol table, and the MAIN__ symbol via the minimal
+ symbol table. */
+ if (sh.st == stProc)
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols,
+ 0, sh.value, psymtab_language, objfile);
+ else
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols,
+ 0, sh.value, psymtab_language, objfile);
+
/* Skip over procedure to next one. */
if (sh.index >= hdr->iauxMax)
{
&sh);
if (sh.st != stEnd)
continue;
+
+ /* Kludge for Irix 5.2 zero fh->adr. */
+ if (!relocatable
+ && (pst->textlow == 0 || procaddr < pst->textlow))
+ pst->textlow = procaddr;
+
high = procaddr + sh.value;
if (high > pst->texthigh)
pst->texthigh = high;
continue;
case stStatic: /* Variable */
- if (sh.sc == scData || sh.sc == scSData || sh.sc == scRData)
- prim_record_minimal_symbol (name, sh.value, mst_file_data,
- objfile);
+ if (SC_IS_DATA (sh.sc))
+ prim_record_minimal_symbol_and_info (name, sh.value,
+ mst_file_data, NULL,
+ SECT_OFF_DATA,
+ NULL,
+ objfile);
else
- prim_record_minimal_symbol (name, sh.value, mst_file_bss,
- objfile);
+ prim_record_minimal_symbol_and_info (name, sh.value,
+ mst_file_bss, NULL,
+ SECT_OFF_BSS,
+ NULL,
+ objfile);
class = LOC_STATIC;
break;
+ case stIndirect:/* Irix5 forward declaration */
+ /* Skip forward declarations from Irix5 cc */
+ goto skip;
+
case stTypedef:/* Typedef */
/* Skip typedefs for forward declarations and opaque
- structs from alpha cc. */
- if (sh.iss == 0)
+ structs from alpha and mips cc. */
+ if (sh.iss == 0 || has_opaque_xref (fh, &sh))
goto skip;
class = LOC_TYPEDEF;
break;
case stBlock: /* { }, str, un, enum*/
/* Do not create a partial symbol for cc unnamed aggregates
and gcc empty aggregates. */
- if ((sh.sc == scInfo || sh.sc == scCommon)
+ if ((sh.sc == scInfo
+ || SC_IS_COMMON(sh.sc))
&& sh.iss != 0
&& sh.index != cur_sdx + 2)
{
- ADD_PSYMBOL_TO_LIST (name, strlen (name),
+ add_psymbol_to_list (name, strlen (name),
STRUCT_NAMESPACE, LOC_TYPEDEF,
- objfile->static_psymbols,
- sh.value,
+ &objfile->static_psymbols,
+ 0, (CORE_ADDR) 0,
psymtab_language, objfile);
}
+ handle_psymbol_enumerators (objfile, fh, sh.st, sh.value);
+
/* Skip over the block */
new_sdx = sh.index;
if (new_sdx <= cur_sdx)
continue;
}
/* Use this gdb symbol */
- ADD_PSYMBOL_TO_LIST (name, strlen (name),
+ add_psymbol_to_list (name, strlen (name),
VAR_NAMESPACE, class,
- objfile->static_psymbols, sh.value,
- psymtab_language, objfile);
+ &objfile->static_psymbols,
+ 0, sh.value, psymtab_language, objfile);
skip:
cur_sdx++; /* Go to next file symbol */
}
enum address_class class;
SYMR *psh;
char *name;
+ CORE_ADDR svalue;
if (ext_ptr->ifd != f_idx)
abort ();
psh = &ext_ptr->asym;
/* Do not add undefined symbols to the partial symbol table. */
- if (psh->sc == scUndefined || psh->sc == scNil)
+ if (SC_IS_UNDEF(psh->sc) || psh->sc == scNil)
continue;
+ svalue = psh->value;
+ switch (psh->sc)
+ {
+ case scText:
+ case scRConst:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ break;
+ case scBss:
+ case scSBss:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ break;
+ }
+
switch (psh->st)
{
case stNil:
continue;
case stProc:
case stStaticProc:
- class = LOC_BLOCK;
- break;
+ /* External procedure symbols have been entered
+ into the minimal symbol table in pass 2 above.
+ Ignore them, as parse_external will ignore them too. */
+ continue;
case stLabel:
class = LOC_LABEL;
break;
debug_info->ssext + psh->iss);
/* Fall through, pretend it's global. */
case stGlobal:
+ /* Global common symbols are resolved by the runtime loader,
+ ignore them. */
+ if (SC_IS_COMMON(psh->sc))
+ continue;
+
class = LOC_STATIC;
break;
}
name = debug_info->ssext + psh->iss;
- ADD_PSYMBOL_ADDR_TO_LIST (name, strlen (name),
- VAR_NAMESPACE, class,
- objfile->global_psymbols,
- (CORE_ADDR) psh->value,
- psymtab_language, objfile);
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, class,
+ &objfile->global_psymbols,
+ 0, svalue,
+ psymtab_language, objfile);
}
}
fdr_to_pst[f_idx].pst = end_psymtab (save_pst,
psymtab_include_list, includes_used,
-1, save_pst->texthigh,
- dependency_list, dependencies_used);
+ dependency_list, dependencies_used, textlow_not_set);
+ includes_used = 0;
+ dependencies_used = 0;
+
if (objfile->ei.entry_point >= save_pst->textlow &&
objfile->ei.entry_point < save_pst->texthigh)
{
objfile->ei.entry_file_lowpc = save_pst->textlow;
objfile->ei.entry_file_highpc = save_pst->texthigh;
}
+
+ /* The objfile has its functions reordered if this partial symbol
+ table overlaps any other partial symbol table.
+ We cannot assume a reordered objfile if a partial symbol table
+ is contained within another partial symbol table, as partial symbol
+ tables for include files with executable code are contained
+ within the partial symbol table for the including source file,
+ and we do not want to flag the objfile reordered for these cases.
+
+ This strategy works well for Irix-5.2 shared libraries, but we
+ might have to use a more elaborate (and slower) algorithm for
+ other cases. */
+ save_pst = fdr_to_pst[f_idx].pst;
+ if (save_pst != NULL
+ && save_pst->textlow != 0
+ && !(objfile->flags & OBJF_REORDERED))
+ {
+ ALL_OBJFILE_PSYMTABS (objfile, pst)
+ {
+ if (save_pst != pst
+ && save_pst->textlow >= pst->textlow
+ && save_pst->textlow < pst->texthigh
+ && save_pst->texthigh > pst->texthigh)
+ {
+ objfile->flags |= OBJF_REORDERED;
+ break;
+ }
+ }
+ }
}
/* Now scan the FDRs for dependencies */
pst->dependencies[pst->number_of_dependencies++] = fdr_to_pst[rh].pst;
}
}
+
+ /* Remove the dummy psymtab created for -O3 images above, if it is
+ still empty, to enable the detection of stripped executables. */
+ if (objfile->psymtabs->next == NULL
+ && objfile->psymtabs->number_of_dependencies == 0
+ && objfile->psymtabs->n_global_syms == 0
+ && objfile->psymtabs->n_static_syms == 0)
+ objfile->psymtabs = NULL;
do_cleanups (old_chain);
}
+/* If the current psymbol has an enumerated type, we need to add
+ all the the enum constants to the partial symbol table. */
+
+static void
+handle_psymbol_enumerators (objfile, fh, stype, svalue)
+ struct objfile *objfile;
+ FDR *fh;
+ int stype;
+ CORE_ADDR svalue;
+{
+ const bfd_size_type external_sym_size = debug_swap->external_sym_size;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = debug_swap->swap_sym_in;
+ char *ext_sym = ((char *) debug_info->external_sym
+ + ((fh->isymBase + cur_sdx + 1) * external_sym_size));
+ SYMR sh;
+ TIR tir;
+
+ switch (stype)
+ {
+ case stEnum:
+ break;
+
+ case stBlock:
+ /* It is an enumerated type if the next symbol entry is a stMember
+ and its auxiliary index is indexNil or its auxiliary entry
+ is a plain btNil or btVoid.
+ Alpha cc -migrate enums are recognized by a zero index and
+ a zero symbol value.
+ DU 4.0 cc enums are recognized by a member type of btEnum without
+ qualifiers and a zero symbol value. */
+ (*swap_sym_in) (cur_bfd, ext_sym, &sh);
+ if (sh.st != stMember)
+ return;
+
+ if (sh.index == indexNil
+ || (sh.index == 0 && svalue == 0))
+ break;
+ (*debug_swap->swap_tir_in) (fh->fBigendian,
+ &(debug_info->external_aux
+ + fh->iauxBase + sh.index)->a_ti,
+ &tir);
+ if ((tir.bt != btNil
+ && tir.bt != btVoid
+ && (tir.bt != btEnum || svalue != 0))
+ || tir.tq0 != tqNil)
+ return;
+ break;
+
+ default:
+ return;
+ }
+
+ for (;;)
+ {
+ char *name;
+
+ (*swap_sym_in) (cur_bfd, ext_sym, &sh);
+ if (sh.st != stMember)
+ break;
+ name = debug_info->ss + cur_fdr->issBase + sh.iss;
+
+ /* Note that the value doesn't matter for enum constants
+ in psymtabs, just in symtabs. */
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols, 0,
+ (CORE_ADDR) 0, psymtab_language, objfile);
+ ext_sym += external_sym_size;
+ }
+}
static char *
-mdebug_next_symbol_text ()
+mdebug_next_symbol_text (objfile)
+ struct objfile *objfile; /* argument objfile is currently unused */
{
SYMR sh;
struct symtab *st;
FDR *fh;
struct linetable *lines;
+ CORE_ADDR lowest_pdr_addr = 0;
if (pst->readin)
return;
if (processing_gcc_compilation != 0)
{
- char *pdr_ptr;
- char *pdr_end;
- int first_pdr;
- unsigned long first_off = 0;
/* This symbol table contains stabs-in-ecoff entries. */
&sh);
name = debug_info->ss + fh->issBase + sh.iss;
valu = sh.value;
- if (ECOFF_IS_STAB (&sh))
+ /* XXX This is a hack. It will go away! */
+ if (ECOFF_IS_STAB (&sh) || (name[0] == '#'))
{
int type_code = ECOFF_UNMARK_STAB (sh.index);
process_one_symbol (type_code, 0, valu, name,
pst->section_offsets, pst->objfile);
}
+ /* Similarly a hack. */
+ else if (name[0] == '#')
+ {
+ process_one_symbol (N_SLINE, 0, valu, name,
+ pst->section_offsets, pst->objfile);
+ }
if (type_code == N_FUN)
{
/* Make up special symbol to contain
obstack_alloc (¤t_objfile->symbol_obstack,
sizeof (struct mips_extra_func_info)));
struct symbol *s = new_symbol (MIPS_EFI_SYMBOL_NAME);
+
+ memset ((PTR) e, 0, sizeof (struct mips_extra_func_info));
SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
SYMBOL_CLASS (s) = LOC_CONST;
- SYMBOL_TYPE (s) = builtin_type_void;
+ SYMBOL_TYPE (s) = mdebug_type_void;
SYMBOL_VALUE (s) = (long) e;
+ e->pdr.framereg = -1;
add_symbol_to_list (s, &local_symbols);
}
}
;
}
else
- /* Handle encoded stab line number. */
- record_line (current_subfile, sh.index, valu);
+ {
+ /* Handle encoded stab line number. */
+ valu += ANOFFSET (pst->section_offsets, SECT_OFF_TEXT);
+ record_line (current_subfile, sh.index, valu);
+ }
}
- else if (sh.st == stProc || sh.st == stStaticProc || sh.st == stEnd)
+ else if (sh.st == stProc || sh.st == stStaticProc
+ || sh.st == stStatic || sh.st == stEnd)
/* These are generated by gcc-2.x, do not complain */
;
else
complain (&stab_unknown_complaint, name);
}
- st = end_symtab (pst->texthigh, 0, 0, pst->objfile, SECT_OFF_TEXT);
+ st = end_symtab (pst->texthigh, pst->objfile, SECT_OFF_TEXT);
end_stabs ();
/* Sort the symbol table now, we are done adding symbols to it.
We must do this before parse_procedure calls lookup_symbol. */
sort_symtab_syms (st);
- /* This may not be necessary for stabs symtabs. FIXME. */
- sort_blocks (st);
+ /* There used to be a call to sort_blocks here, but this should not
+ be necessary for stabs symtabs. And as sort_blocks modifies the
+ start address of the GLOBAL_BLOCK to the FIRST_LOCAL_BLOCK,
+ it did the wrong thing if the first procedure in a file was
+ generated via asm statements. */
/* Fill in procedure info next. */
- first_pdr = 1;
- pdr_ptr = ((char *) debug_info->external_pdr
- + fh->ipdFirst * external_pdr_size);
- pdr_end = pdr_ptr + fh->cpd * external_pdr_size;
- for (; pdr_ptr < pdr_end; pdr_ptr += external_pdr_size)
+ if (fh->cpd > 0)
{
- PDR pr;
-
- (*swap_pdr_in) (cur_bfd, pdr_ptr, &pr);
- if (first_pdr)
+ PDR *pr_block;
+ struct cleanup *old_chain;
+ char *pdr_ptr;
+ char *pdr_end;
+ PDR *pdr_in;
+ PDR *pdr_in_end;
+
+ pr_block = (PDR *) xmalloc (fh->cpd * sizeof (PDR));
+ old_chain = make_cleanup (free, pr_block);
+
+ pdr_ptr = ((char *) debug_info->external_pdr
+ + fh->ipdFirst * external_pdr_size);
+ pdr_end = pdr_ptr + fh->cpd * external_pdr_size;
+ pdr_in = pr_block;
+ for (;
+ pdr_ptr < pdr_end;
+ pdr_ptr += external_pdr_size, pdr_in++)
{
- first_off = pr.adr;
- first_pdr = 0;
+ (*swap_pdr_in) (cur_bfd, pdr_ptr, pdr_in);
+
+ /* Determine lowest PDR address, the PDRs are not always
+ sorted. */
+ if (pdr_in == pr_block)
+ lowest_pdr_addr = pdr_in->adr;
+ else if (pdr_in->adr < lowest_pdr_addr)
+ lowest_pdr_addr = pdr_in->adr;
}
- parse_procedure (&pr, st, first_off);
+
+ pdr_in = pr_block;
+ pdr_in_end = pdr_in + fh->cpd;
+ for (; pdr_in < pdr_in_end; pdr_in++)
+ parse_procedure (pdr_in, st, pst);
+
+ do_cleanups (old_chain);
}
}
else
{
/* This symbol table contains ordinary ecoff entries. */
- /* FIXME: doesn't use pst->section_offsets. */
-
int f_max;
int maxlines;
EXTR *ext_ptr;
top_stack->cur_st = st;
top_stack->cur_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (st),
STATIC_BLOCK);
- BLOCK_START (top_stack->cur_block) = fh ? fh->adr : 0;
+ BLOCK_START (top_stack->cur_block) = pst->textlow;
BLOCK_END (top_stack->cur_block) = 0;
top_stack->blocktype = stFile;
top_stack->maxsyms = 2 * f_max;
top_stack->cur_type = 0;
top_stack->procadr = 0;
top_stack->numargs = 0;
+ found_ecoff_debugging_info = 0;
if (fh)
{
(*swap_sym_in) (cur_bfd, sym_ptr, &sh);
c = parse_symbol (&sh,
debug_info->external_aux + fh->iauxBase,
- sym_ptr, fh->fBigendian);
+ sym_ptr, fh->fBigendian, pst->section_offsets);
sym_ptr += c * external_sym_size;
}
for (;
pdr_ptr < pdr_end;
pdr_ptr += external_pdr_size, pdr_in++)
- (*swap_pdr_in) (cur_bfd, pdr_ptr, pdr_in);
+ {
+ (*swap_pdr_in) (cur_bfd, pdr_ptr, pdr_in);
+
+ /* Determine lowest PDR address, the PDRs are not always
+ sorted. */
+ if (pdr_in == pr_block)
+ lowest_pdr_addr = pdr_in->adr;
+ else if (pdr_in->adr < lowest_pdr_addr)
+ lowest_pdr_addr = pdr_in->adr;
+ }
- parse_lines (fh, pr_block, lines, maxlines);
+ parse_lines (fh, pr_block, lines, maxlines, pst, lowest_pdr_addr);
if (lines->nitems < fh->cline)
lines = shrink_linetable (lines);
pdr_in = pr_block;
pdr_in_end = pdr_in + fh->cpd;
for (; pdr_in < pdr_in_end; pdr_in++)
- parse_procedure (pdr_in, 0, pr_block->adr);
+ parse_procedure (pdr_in, 0, pst);
do_cleanups (old_chain);
}
ext_ptr = PST_PRIVATE (pst)->extern_tab;
for (i = PST_PRIVATE (pst)->extern_count; --i >= 0; ext_ptr++)
- parse_external (ext_ptr, 1, fh->fBigendian);
+ parse_external (ext_ptr, fh->fBigendian, pst->section_offsets);
/* If there are undefined symbols, tell the user.
The alpha has an undefined symbol for every symbol that is
}
pop_parse_stack ();
+ st->primary = 1;
+
/* Sort the symbol table now, we are done adding symbols to it.*/
sort_symtab_syms (st);
\f
/* Ancillary parsing procedures. */
+/* Return 1 if the symbol pointed to by SH has a cross reference
+ to an opaque aggregate type, else 0. */
+
+static int
+has_opaque_xref (fh, sh)
+ FDR *fh;
+ SYMR *sh;
+{
+ TIR tir;
+ union aux_ext *ax;
+ RNDXR rn[1];
+ unsigned int rf;
+
+ if (sh->index == indexNil)
+ return 0;
+
+ ax = debug_info->external_aux + fh->iauxBase + sh->index;
+ (*debug_swap->swap_tir_in) (fh->fBigendian, &ax->a_ti, &tir);
+ if (tir.bt != btStruct && tir.bt != btUnion && tir.bt != btEnum)
+ return 0;
+
+ ax++;
+ (*debug_swap->swap_rndx_in) (fh->fBigendian, &ax->a_rndx, rn);
+ if (rn->rfd == 0xfff)
+ rf = AUX_GET_ISYM (fh->fBigendian, ax + 1);
+ else
+ rf = rn->rfd;
+ if (rf != -1)
+ return 0;
+ return 1;
+}
+
/* Lookup the type at relative index RN. Return it in TPP
if found and in any event come up with its name PNAME.
BIGEND says whether aux symbols are big-endian or not (from fh->fBigendian).
*tpp = (struct type *)NULL;
- ecoff_swap_rndx_in (bigend, &ax->a_rndx, rn);
+ (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, rn);
/* Escape index means 'the next one' */
if (rn->rfd == 0xfff)
}
/* mips cc uses a rf of -1 for opaque struct definitions.
- Set TYPE_FLAG_STUB for these types so that check_stub_type will
+ Set TYPE_FLAG_STUB for these types so that check_typedef will
resolve them if the struct gets defined in another compilation unit. */
if (rf == -1)
{
(*debug_swap->swap_sym_in) (cur_bfd, esh, &sh);
/* Make sure that this type of cross reference can be handled. */
- if (sh.sc != scInfo
- || (sh.st != stBlock && sh.st != stTypedef
- && sh.st != stStruct && sh.st != stUnion
- && sh.st != stEnum))
+ if ((sh.sc != scInfo
+ || (sh.st != stBlock && sh.st != stTypedef && sh.st != stIndirect
+ && sh.st != stStruct && sh.st != stUnion
+ && sh.st != stEnum))
+ && (sh.st != stBlock || !SC_IS_COMMON(sh.sc)))
{
/* File indirect entry is corrupt. */
*pname = "<illegal>";
{
/* We have not yet seen this type. */
- if (sh.iss == 0 && sh.st == stTypedef)
+ if ((sh.iss == 0 && sh.st == stTypedef) || sh.st == stIndirect)
{
TIR tir;
For these the type will be void. This is a bad design decision
as cross referencing across compilation units is impossible
due to the missing name.
- b) forward declarations of structs/unions/enums which are defined
- later in this file or in another file in the same compilation
- unit. Simply cross reference those again to get the
- true type.
+ b) forward declarations of structs/unions/enums/typedefs which
+ are defined later in this file or in another file in the same
+ compilation unit. Irix5 cc uses a stIndirect symbol for this.
+ Simply cross reference those again to get the true type.
The forward references are not entered in the pending list and
in the symbol table. */
- ecoff_swap_tir_in (bigend,
- &(debug_info->external_aux
- + fh->iauxBase + sh.index)->a_ti,
- &tir);
+ (*debug_swap->swap_tir_in) (bigend,
+ &(debug_info->external_aux
+ + fh->iauxBase + sh.index)->a_ti,
+ &tir);
if (tir.tq0 != tqNil)
complain (&illegal_forward_tq0_complaint, sym_name);
switch (tir.bt)
fh->fBigendian, sym_name);
break;
+ case btTypedef:
+ /* Follow a forward typedef. This might recursively
+ call cross_ref till we get a non typedef'ed type.
+ FIXME: This is not correct behaviour, but gdb currently
+ cannot handle typedefs without type copying. Type
+ copying is impossible as we might have mutual forward
+ references between two files and the copied type would not
+ get filled in when we later parse its definition. */
+ *tpp = parse_type (xref_fd,
+ debug_info->external_aux + fh->iauxBase,
+ sh.index,
+ (int *)NULL,
+ fh->fBigendian,
+ debug_info->ss + fh->issBase + sh.iss);
+ add_pending (fh, esh, *tpp);
+ break;
+
default:
complain (&illegal_forward_bt_complaint, tir.bt, sym_name);
*tpp = init_type (type_code, 0, 0, (char *) NULL,
mylookup_symbol (name, block, namespace, class)
char *name;
register struct block *block;
- enum namespace namespace;
+ namespace_enum namespace;
enum address_class class;
{
register int bot, top, inc;
BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
s->free_code = free_linetable;
-
+ s->debugformat = obsavestring ("ECOFF", 5,
+ &objfile -> symbol_obstack);
return (s);
}
/* Allocate a new partial_symtab NAME */
static struct partial_symtab *
-new_psymtab (name, objfile)
+new_psymtab (name, objfile, section_offsets)
char *name;
struct objfile *objfile;
+ struct section_offsets *section_offsets;
{
struct partial_symtab *psymtab;
psymtab = allocate_psymtab (name, objfile);
+ psymtab->section_offsets = section_offsets;
/* Keep a backpointer to the file's symbols */
sizeof (struct symbol)));
memset ((PTR) s, 0, sizeof (*s));
- SYMBOL_NAME (s) = name;
+ SYMBOL_NAME (s) = obsavestring (name, strlen (name),
+ ¤t_objfile->symbol_obstack);
SYMBOL_LANGUAGE (s) = psymtab_language;
SYMBOL_INIT_DEMANGLED_NAME (s, ¤t_objfile->symbol_obstack);
return s;
struct section_offsets *section_offsets;
{
bfd *abfd = objfile->obfd;
- char *buf;
struct ecoff_debug_info *info;
- buf = alloca (swap->external_hdr_size);
- if (bfd_get_section_contents (abfd, sec, buf, (file_ptr) 0,
- swap->external_hdr_size) == false)
- perror_with_name (bfd_get_filename (abfd));
-
info = ((struct ecoff_debug_info *)
obstack_alloc (&objfile->psymbol_obstack,
sizeof (struct ecoff_debug_info)));
- (*swap->swap_hdr_in) (abfd, buf, &info->symbolic_header);
-
- /* The offsets in symbolic_header are file offsets, not section
- offsets. Strangely, on Irix 5 the information is not entirely
- within the .mdebug section. There are parts of an executable
- file which are not within any ELF section at all. This means
- that we must read the information using bfd_read. */
-
-#define READ(ptr, count, off, size, type) \
- do \
- { \
- if (info->symbolic_header.count == 0) \
- info->ptr = (type) NULL; \
- else \
- { \
- info->ptr = ((type) \
- obstack_alloc (&objfile->psymbol_obstack, \
- (info->symbolic_header.count \
- * size))); \
- if (bfd_seek (abfd, info->symbolic_header.off, SEEK_SET) < 0 \
- || (bfd_read ((PTR) info->ptr, size, \
- info->symbolic_header.count, abfd) \
- != info->symbolic_header.count * size)) \
- perror_with_name (bfd_get_filename (abfd)); \
- } \
- } \
- while (0)
-
- READ (line, cbLine, cbLineOffset, sizeof (unsigned char), unsigned char *);
- READ (external_dnr, idnMax, cbDnOffset, swap->external_dnr_size, PTR);
- READ (external_pdr, ipdMax, cbPdOffset, swap->external_pdr_size, PTR);
- READ (external_sym, isymMax, cbSymOffset, swap->external_sym_size, PTR);
- READ (external_opt, ioptMax, cbOptOffset, swap->external_opt_size, PTR);
- READ (external_aux, iauxMax, cbAuxOffset, sizeof (union aux_ext),
- union aux_ext *);
- READ (ss, issMax, cbSsOffset, sizeof (char), char *);
- READ (ssext, issExtMax, cbSsExtOffset, sizeof (char), char *);
- READ (external_fdr, ifdMax, cbFdOffset, swap->external_fdr_size, PTR);
- READ (external_rfd, crfd, cbRfdOffset, swap->external_rfd_size, PTR);
- READ (external_ext, iextMax, cbExtOffset, swap->external_ext_size, PTR);
-
-#undef READ
-
- info->fdr = NULL;
+ if (!(*swap->read_debug_info) (abfd, sec, info))
+ error ("Error reading ECOFF debugging information: %s",
+ bfd_errmsg (bfd_get_error ()));
mdebug_build_psymtabs (objfile, swap, info, section_offsets);
}
/* FIXME: This function is called only by mips-tdep.c. It needs to be
here because it calls functions defined in this file, but perhaps
- this could be handled in a better way. */
+ this could be handled in a better way. Only compile it in when
+ tm-mips.h is included. */
+
+#ifdef TM_MIPS_H
void
fixup_sigtramp ()
SYMBOL_CLASS (s) = LOC_BLOCK;
SYMBOL_TYPE (s) = init_type (TYPE_CODE_FUNC, 4, 0, (char *) NULL,
st->objfile);
- TYPE_TARGET_TYPE (SYMBOL_TYPE (s)) = builtin_type_void;
+ TYPE_TARGET_TYPE (SYMBOL_TYPE (s)) = mdebug_type_void;
/* Need a block to allocate MIPS_EFI_SYMBOL_NAME in */
b = new_block (1);
SYMBOL_VALUE (s) = (long) e;
SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
SYMBOL_CLASS (s) = LOC_CONST;
- SYMBOL_TYPE (s) = builtin_type_void;
+ SYMBOL_TYPE (s) = mdebug_type_void;
current_objfile = NULL;
}
BLOCK_SYM (b, BLOCK_NSYMS (b)++) = s;
}
+#endif /* TM_MIPS_H */
+
void
_initialize_mdebugread ()
{
- /* Missing basic types */
+ mdebug_type_void =
+ init_type (TYPE_CODE_VOID, 1,
+ 0,
+ "void", (struct objfile *) NULL);
+ mdebug_type_char =
+ init_type (TYPE_CODE_INT, 1,
+ 0,
+ "char", (struct objfile *) NULL);
+ mdebug_type_unsigned_char =
+ init_type (TYPE_CODE_INT, 1,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned char", (struct objfile *) NULL);
+ mdebug_type_short =
+ init_type (TYPE_CODE_INT, 2,
+ 0,
+ "short", (struct objfile *) NULL);
+ mdebug_type_unsigned_short =
+ init_type (TYPE_CODE_INT, 2,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned short", (struct objfile *) NULL);
+ mdebug_type_int_32 =
+ init_type (TYPE_CODE_INT, 4,
+ 0,
+ "int", (struct objfile *) NULL);
+ mdebug_type_unsigned_int_32 =
+ init_type (TYPE_CODE_INT, 4,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned int", (struct objfile *) NULL);
+ mdebug_type_int_64 =
+ init_type (TYPE_CODE_INT, 8,
+ 0,
+ "int", (struct objfile *) NULL);
+ mdebug_type_unsigned_int_64 =
+ init_type (TYPE_CODE_INT, 8,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned int", (struct objfile *) NULL);
+ mdebug_type_long_32 =
+ init_type (TYPE_CODE_INT, 4,
+ 0,
+ "long", (struct objfile *) NULL);
+ mdebug_type_unsigned_long_32 =
+ init_type (TYPE_CODE_INT, 4,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long", (struct objfile *) NULL);
+ mdebug_type_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ 0,
+ "long", (struct objfile *) NULL);
+ mdebug_type_unsigned_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long", (struct objfile *) NULL);
+ mdebug_type_long_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ 0,
+ "long long", (struct objfile *) NULL);
+ mdebug_type_unsigned_long_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long long", (struct objfile *) NULL);
+ mdebug_type_adr_32 =
+ init_type (TYPE_CODE_PTR, 4,
+ TYPE_FLAG_UNSIGNED,
+ "adr_32", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_adr_32) = mdebug_type_void;
+ mdebug_type_adr_64 =
+ init_type (TYPE_CODE_PTR, 8,
+ TYPE_FLAG_UNSIGNED,
+ "adr_64", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_adr_64) = mdebug_type_void;
+ mdebug_type_float =
+ init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "float", (struct objfile *) NULL);
+ mdebug_type_double =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double", (struct objfile *) NULL);
+ mdebug_type_complex =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_complex) = mdebug_type_float;
+ mdebug_type_double_complex =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double complex", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_double_complex) = mdebug_type_double;
/* Is a "string" the way btString means it the same as TYPE_CODE_STRING?
FIXME. */
0, "string",
(struct objfile *) NULL);
- mdebug_type_complex =
- init_type (TYPE_CODE_ERROR,
- TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
- 0, "complex",
- (struct objfile *) NULL);
- mdebug_type_double_complex =
- init_type (TYPE_CODE_ERROR,
- TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
- 0, "double complex",
- (struct objfile *) NULL);
-
/* We use TYPE_CODE_INT to print these as integers. Does this do any
good? Would we be better off with TYPE_CODE_ERROR? Should
TYPE_CODE_ERROR print things in hex if it knows the size? */
TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
0, "floating decimal",
(struct objfile *) NULL);
+
+ nodebug_func_symbol_type = init_type (TYPE_CODE_FUNC, 1, 0,
+ "<function, no debug info>", NULL);
+ TYPE_TARGET_TYPE (nodebug_func_symbol_type) = mdebug_type_int;
+ nodebug_var_symbol_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+ "<variable, no debug info>", NULL);
}