#ifndef RA_REGNUM
#define RA_REGNUM 0
#endif
-#ifndef FP0_REGNUM
-#define FP0_REGNUM 0
-#endif
#endif
#ifdef USG
#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
+
+/* Information is passed among various mipsread routines for accessing
+ symbol files. A pointer to this structure is kept in the sym_private
+ field of the objfile struct. */
+
+struct ecoff_symfile_info {
+ struct mips_pending **pending_list;
+};
+#define ECOFF_SYMFILE_INFO(o) ((struct ecoff_symfile_info *)((o)->sym_private))
+#define ECOFF_PENDING_LIST(o) (ECOFF_SYMFILE_INFO(o)->pending_list)
+
+
/* 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.
bfd *cur_bfd;
EXTR *extern_tab; /* Pointer to external symbols for this file. */
int extern_count; /* Size of extern_tab. */
- struct mips_pending **pending_list;
enum language pst_language;
};
struct complaint unexpected_type_code_complaint =
{"unexpected type code for %s", 0, 0};
-/* Macros and extra defs */
+struct complaint unable_to_cross_ref_complaint =
+{"unable to cross ref btTypedef for %s", 0, 0};
-/* Already-parsed symbols are marked specially */
+struct complaint illegal_forward_tq0_complaint =
+{"illegal tq0 in forward typedef for %s", 0, 0};
-#define stParsed stType
+struct complaint illegal_forward_bt_complaint =
+{"illegal bt %d in forward typedef for %s", 0, 0};
+
+/* Macros and extra defs */
/* Puns: hard to find whether -g was used and how */
read_the_mips_symtab PARAMS ((bfd *));
static int
-upgrade_type PARAMS ((struct type **, int, union aux_ext *, int));
+upgrade_type PARAMS ((int, struct type **, int, union aux_ext *, int));
static void
parse_partial_symbols PARAMS ((struct objfile *,
struct section_offsets *));
static int
-cross_ref PARAMS ((union aux_ext *, struct type **, enum type_code, char **,
- int, char *));
+cross_ref PARAMS ((int, union aux_ext *, struct type **, enum type_code,
+ char **, int, char *));
static void
fixup_sigtramp PARAMS ((void));
static struct blockvector *
new_bvect PARAMS ((int));
+static int
+parse_symbol PARAMS ((SYMR *, union aux_ext *, char *, int));
+
static struct type *
-parse_type PARAMS ((union aux_ext *, int *, int, char *));
+parse_type PARAMS ((int, union aux_ext *, int *, int, char *));
static struct symbol *
mylookup_symbol PARAMS ((char *, struct block *, enum namespace,
{
mfree (objfile->md, objfile->sym_private);
}
- objfile->sym_private = NULL;
+ objfile->sym_private = (PTR)
+ xmmalloc (objfile->md, sizeof (struct ecoff_symfile_info));
}
static void
struct pst_map
{
struct partial_symtab *pst; /* the psymtab proper */
- int n_globals; /* exported globals (external symbols) */
- int globals_offset; /* cumulative */
+ long n_globals; /* exported globals (external symbols) */
+ long globals_offset; /* cumulative */
};
int maxsyms; /* Max symbols in this block. */
struct type *cur_type; /* Type we parse fields for. */
int cur_field; /* Field number in cur_type. */
- int procadr; /* Start addres of this procedure */
+ CORE_ADDR procadr; /* Start addres of this procedure */
int numargs; /* Its argument count */
}
duplications we keep a quick fixup table, an array
of lists of references indexed by file descriptor */
-static struct mips_pending
+struct mips_pending
{
struct mips_pending *next; /* link */
char *s; /* the unswapped symbol */
struct type *t; /* its partial type descriptor */
-} **pending_list;
+};
-/* Check whether we already saw symbol SH in file FH as undefined */
+/* Check whether we already saw symbol SH in file FH */
static struct mips_pending *
is_pending_symbol (fh, sh)
{
int f_idx = fh - ecoff_data (cur_bfd)->fdr;
register struct mips_pending *p;
+ struct mips_pending **pending_list = ECOFF_PENDING_LIST (current_objfile);
/* Linear search is ok, list is typically no more than 10 deep */
for (p = pending_list[f_idx]; p; p = p->next)
return p;
}
-/* Add a new undef symbol SH of type T */
+/* Add a new symbol SH of type T */
static void
add_pending (fh, sh, t)
/* Make sure we do not make duplicates */
if (!p)
{
- p = (struct mips_pending *) xmalloc (sizeof (*p));
+ struct mips_pending **pending_list = ECOFF_PENDING_LIST (current_objfile);
+
+ p = ((struct mips_pending *)
+ obstack_alloc (¤t_objfile->psymbol_obstack,
+ sizeof (struct mips_pending)));
p->s = sh;
p->t = t;
p->next = pending_list[f_idx];
pending_list[f_idx] = p;
}
}
-
-/* Throw away undef entries when done with file index F_IDX */
-/* FIXME -- storage leak. This is never called!!! --gnu */
-
-#if 0
-
-static void
-free_pending (f_idx)
- int f_idx;
-{
- register struct mips_pending *p, *q;
-
- for (p = pending_list[f_idx]; p; p = q)
- {
- q = p->next;
- free ((PTR) p);
- }
- pending_list[f_idx] = 0;
-}
-
-#endif
-
\f
/* Parsing Routines proper. */
EXT_SH points to the unswapped symbol, which is needed for struct,
union, etc., types; it is NULL for an EXTR. BIGEND says whether
aux symbols are big-endian or little-endian. Return count of
- SYMR's handled (normally one).
-
- FIXME: This modifies the symbol, but the only way we have to save
- the modified information is to stuff it back into the BFD data. */
+ SYMR's handled (normally one). */
static int
parse_symbol (sh, ax, ext_sh, bigend)
int count = 1;
enum address_class class;
TIR tir;
+ long svalue = sh->value;
if (ext_sh == (char *) NULL)
name = ecoff_data (cur_bfd)->ssext + sh->iss;
if (sh->sc == scRegister)
{
class = LOC_REGISTER;
- if (sh->value > 31)
- sh->value += FP0_REGNUM - 32;
+ svalue = ECOFF_REG_TO_REGNUM (svalue);
}
else
class = LOC_LOCAL;
b = top_stack->cur_block;
s = new_symbol (name);
- SYMBOL_VALUE (s) = sh->value;
+ SYMBOL_VALUE (s) = svalue;
data: /* Common code for symbols describing data */
SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
sh->index == 0xfffff)
SYMBOL_TYPE (s) = builtin_type_int; /* undefined? */
else
- SYMBOL_TYPE (s) = parse_type (ax + sh->index, 0, bigend, name);
+ SYMBOL_TYPE (s) = parse_type (cur_fd, ax + sh->index, 0, bigend, name);
/* Value of a data symbol is its memory address */
break;
case scRegister:
/* Pass by value in register. */
SYMBOL_CLASS(s) = LOC_REGPARM;
- if (sh->value > 31)
- sh->value += FP0_REGNUM-32;
+ svalue = ECOFF_REG_TO_REGNUM (svalue);
break;
case scVar:
/* Pass by reference on stack. */
case scVarRegister:
/* Pass by reference in register. */
SYMBOL_CLASS(s) = LOC_REGPARM_ADDR;
+ svalue = ECOFF_REG_TO_REGNUM (svalue);
break;
default:
/* Pass by value on stack. */
SYMBOL_CLASS(s) = LOC_ARG;
break;
}
- SYMBOL_VALUE (s) = sh->value;
- SYMBOL_TYPE (s) = parse_type (ax + sh->index, 0, bigend, 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 */
if (sh->sc == scUndefined || sh->sc == scNil)
t = builtin_type_int;
else
- t = parse_type (ax + sh->index + 1, 0, bigend, name);
+ t = parse_type (cur_fd, ax + sh->index + 1, 0, bigend, name);
b = top_stack->cur_block;
if (sh->st == stProc)
{
/* Generate a template for the type of this function. The
types of the arguments will be added as we read the symbol
table. */
- bcopy (SYMBOL_TYPE (s), lookup_function_type (t), sizeof (struct type));
+ memcpy (lookup_function_type (t), SYMBOL_TYPE (s), sizeof (struct type));
#else
SYMBOL_TYPE (s) = lookup_function_type (t);
#endif
top_stack->cur_field = -1;
top_stack->procadr = sh->value;
top_stack->numargs = 0;
-
- sh->value = (long) SYMBOL_TYPE (s);
- sh->st = stParsed;
break;
/* Beginning of code for structure, union, and enum definitions.
push_parse_stack ();
top_stack->blocktype = stBlock;
- s = new_symbol (name);
- SYMBOL_NAMESPACE (s) = STRUCT_NAMESPACE;
- SYMBOL_CLASS (s) = LOC_TYPEDEF;
- SYMBOL_VALUE (s) = 0;
- add_symbol (s, top_stack->cur_block);
-
/* First count the number of fields and the highest value. */
nfields = 0;
max_value = 0;
case stUnion:
case stEnum:
case stStruct:
- case stParsed:
{
#if 0
/* This is a no-op; is it trying to tell us something
else
type_code = TYPE_CODE_STRUCT;
- /* If this type was expected, use its partial definition */
+ /* Create a new type or use the pending type. */
pend = is_pending_symbol (cur_fdr, ext_sh);
- if (pend != (struct mips_pending *) NULL)
+ if (pend == (struct mips_pending *) NULL)
+ {
+ t = new_type (NULL);
+ add_pending (cur_fdr, ext_sh, t);
+ }
+ else
t = pend->t;
+
+ /* Alpha cc unnamed structs do not get a tag name. */
+ if (sh->iss == 0)
+ TYPE_TAG_NAME (t) = NULL;
else
- t = new_type (NULL);
+ TYPE_TAG_NAME (t) = obconcat (¤t_objfile->symbol_obstack,
+ "", "", name);
- TYPE_TAG_NAME (t) = obconcat (¤t_objfile->symbol_obstack,
- "", "", name);
TYPE_CODE (t) = type_code;
TYPE_LENGTH (t) = sh->value;
TYPE_NFIELDS (t) = nfields;
TYPE_FIELDS (t) = f = ((struct field *)
TYPE_ALLOC (t,
nfields * sizeof (struct field)));
- /* Handle opaque struct definitions. */
- if (TYPE_NFIELDS (t) == 0)
- {
- TYPE_FLAGS (t) |= TYPE_FLAG_STUB;
- SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
- }
if (type_code == TYPE_CODE_ENUM)
{
f++;
}
}
- SYMBOL_TYPE (s) = t;
/* make this the current type */
top_stack->cur_type = t;
top_stack->cur_field = 0;
- /* Mark that symbol has a type, and say which one */
- sh->value = (long) t;
- sh->st = stParsed;
+
+ /* Do not create a symbol for alpha cc unnamed structs. */
+ if (sh->iss == 0)
+ break;
+ s = new_symbol (name);
+ SYMBOL_NAMESPACE (s) = STRUCT_NAMESPACE;
+ SYMBOL_CLASS (s) = LOC_TYPEDEF;
+ SYMBOL_VALUE (s) = 0;
+ SYMBOL_TYPE (s) = t;
+
+ /* gcc puts out an empty struct for an opaque struct definitions. */
+ if (TYPE_NFIELDS (t) == 0)
+ {
+ TYPE_FLAGS (t) |= TYPE_FLAG_STUB;
+ SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
+ }
+ add_symbol (s, top_stack->cur_block);
break;
/* End of local variables shared by struct, union, enum, and
e = ((struct mips_extra_func_info *)
obstack_alloc (¤t_objfile->symbol_obstack,
sizeof (struct mips_extra_func_info)));
- SYMBOL_VALUE (s) = (int) e;
+ SYMBOL_VALUE (s) = (long) e;
e->numargs = top_stack->numargs;
add_symbol (s, top_stack->cur_block);
f->name = name;
f->bitpos = sh->value;
f->bitsize = 0;
- f->type = parse_type (ax + sh->index, &f->bitsize, bigend, name);
+ f->type = parse_type (cur_fd, ax + sh->index, &f->bitsize, bigend, name);
break;
case stTypedef: /* type definition */
+ /* Typedefs for forward declarations and opaque structs from alpha cc
+ are handled by cross_ref, skip them. */
+ if (sh->iss == 0)
+ break;
+
+ /* Parse the type or use the pending type. */
+ pend = is_pending_symbol (cur_fdr, ext_sh);
+ if (pend == (struct mips_pending *) NULL)
+ {
+ t = parse_type (cur_fd, ax + sh->index, (int *)NULL, bigend, name);
+ add_pending (cur_fdr, ext_sh, t);
+ }
+ else
+ t = pend->t;
+
+ /* mips cc puts out a typedef with the name of the struct for forward
+ declarations. These should not go into the symbol table and
+ TYPE_NAME should not be set for them.
+ They can't be distinguished from an intentional typedef to
+ the same name however:
+ x.h:
+ struct x { int ix; int jx; };
+ struct xx;
+ x.c:
+ typedef struct x x;
+ struct xx {int ixx; int jxx; };
+ 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. */
+
s = new_symbol (name);
SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
SYMBOL_CLASS (s) = LOC_TYPEDEF;
SYMBOL_BLOCK_VALUE (s) = top_stack->cur_block;
+ SYMBOL_TYPE (s) = t;
add_symbol (s, top_stack->cur_block);
- SYMBOL_TYPE (s) = parse_type (ax + sh->index, 0, bigend, name);
- sh->value = (long) SYMBOL_TYPE (s);
- sh->st = stParsed;
- if (TYPE_TAG_NAME (SYMBOL_TYPE (s)) != NULL
- && STREQ (TYPE_TAG_NAME (SYMBOL_TYPE (s)), "<undefined>"))
- {
- /* mips cc puts out a stTypedef for opaque struct definitions. */
- TYPE_FLAGS (SYMBOL_TYPE (s)) |= TYPE_FLAG_STUB;
- }
+
/* Incomplete definitions of structs should not get a name. */
if (TYPE_NAME (SYMBOL_TYPE (s)) == NULL
&& (TYPE_NFIELDS (SYMBOL_TYPE (s)) != 0
they are big-endian or little-endian (from fh->fBigendian). */
static struct type *
-parse_type (ax, bs, bigend, sym_name)
+parse_type (fd, ax, bs, bigend, sym_name)
+ int fd;
union aux_ext *ax;
int *bs;
int bigend;
0, /* btBit */
0, /* btPicture */
&builtin_type_void, /* btVoid */
- &builtin_type_long_long, /* btLongLong */
- &builtin_type_unsigned_long_long, /* btULongLong */
+ 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 */
};
TIR t[1];
type_code = TYPE_CODE_SET;
break;
case btTypedef:
+ /* alpha cc uses this for typedefs. The true type will be
+ obtained by crossreferencing below. */
+ type_code = TYPE_CODE_ERROR;
+ break;
default:
complain (&basic_type_complaint, t->bt, sym_name);
return builtin_type_int;
{
char *name;
- /* Try to cross reference this type */
- ax += cross_ref (ax, &tp, type_code, &name, bigend, sym_name);
- /* reading .o file ? */
+ /* Try to cross reference this type, build new type on failure. */
+ ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name);
if (tp == (struct type *) NULL)
- tp = init_type (type_code, 0, 0, (char *) NULL,
- (struct objfile *) NULL);
+ tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile);
/* Make sure that TYPE_CODE(tp) has an expected type code.
Any type may be returned from cross_ref if file indirect entries
{
/* Usually, TYPE_CODE(tp) is already type_code. The main
- exception is if we guessed wrong re struct/union/enum. */
- if (TYPE_CODE (tp) != type_code)
+ exception is if we guessed wrong re struct/union/enum.
+ But for struct vs. union a wrong guess is harmless, so
+ don't complain(). */
+ if ((TYPE_CODE (tp) == TYPE_CODE_ENUM
+ && type_code != TYPE_CODE_ENUM)
+ || (TYPE_CODE (tp) != TYPE_CODE_ENUM
+ && type_code == TYPE_CODE_ENUM))
{
complain (&bad_tag_guess_complaint, sym_name);
+ }
+
+ if (TYPE_CODE (tp) != type_code)
+ {
TYPE_CODE (tp) = type_code;
}
+
/* Do not set the tag name if it is a compiler generated tag name
(.Fxx or .xxfake or empty) for unnamed struct/union/enums. */
if (name[0] == '.' || name[0] == '\0')
{
char *name;
- /* Try to cross reference this type */
- ax += cross_ref (ax, &tp, type_code, &name, bigend, sym_name);
- /* reading .o file ? */
+ /* Try to cross reference this type, build new type on failure. */
+ ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name);
if (tp == (struct type *) NULL)
- tp = init_type (type_code, 0, 0, (char *) NULL,
- (struct objfile *) NULL);
+ tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile);
/* Make sure that TYPE_CODE(tp) has an expected type code.
Any type may be returned from cross_ref if file indirect entries
¤t_objfile->type_obstack);
}
}
+ if (t->bt == btTypedef)
+ {
+ char *name;
+
+ /* Try to cross reference this type, it should succeed. */
+ ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name);
+ if (tp == (struct type *) NULL)
+ {
+ complain (&unable_to_cross_ref_complaint, sym_name);
+ tp = builtin_type_int;
+ }
+ }
/* Deal with range types */
if (t->bt == btRange)
than 6 the game will continue in the next aux */
#define PARSE_TQ(tq) \
- if (t->tq != tqNil) ax += upgrade_type(&tp, t->tq, ax, bigend);
+ if (t->tq != tqNil) ax += upgrade_type(fd, &tp, t->tq, ax, bigend);
again:PARSE_TQ (tq0);
PARSE_TQ (tq1);
Returns the number of aux symbols we parsed. */
static int
-upgrade_type (tpp, tq, ax, bigend)
+upgrade_type (fd, tpp, tq, ax, bigend)
+ int fd;
struct type **tpp;
int tq;
union aux_ext *ax;
rf = AUX_GET_ISYM (bigend, ax);
off++;
}
- fh = get_rfd (cur_fd, rf);
+ fh = get_rfd (fd, rf);
- indx = parse_type ((ecoff_data (cur_bfd)->external_aux
+ indx = parse_type (fd,
+ (ecoff_data (cur_bfd)->external_aux
+ fh->iauxBase
+ id),
(int *) NULL, bigend, "<array index>");
/* Note that the case of a symbol with indexNil must be handled
anyways by parse_symbol(). */
parse_symbol (&es->asym, ax, (char *) NULL, bigend);
- /* Note that parse_symbol changed es->asym. */
break;
default:
break;
k = 0;
for (j = 0; j < fh->cpd; j++, pr++)
{
- int l, halt;
+ long l, halt;
unsigned long adr;
/* No code for this one */
FDR_IDX (pst) = -1;
}
+ /* Allocate the global pending list. */
+ ECOFF_PENDING_LIST (objfile) =
+ ((struct mips_pending **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ hdr->ifdMax * sizeof (struct mips_pending *)));
+ memset ((PTR) ECOFF_PENDING_LIST (objfile), 0,
+ hdr->ifdMax * sizeof (struct mips_pending *));
+
/* Pass 0 over external syms: swap them in. */
ext_block = (EXTR *) xmalloc (hdr->iextMax * sizeof (EXTR));
make_cleanup (free, ext_block);
{
case stProc:
break;
+ case stStaticProc:
+ ms_type = mst_file_text;
+ break;
case stGlobal:
if (ext_in->asym.sc == scData
|| ext_in->asym.sc == scSData
/* The way to turn this into a symtab is to call... */
pst->read_symtab = mipscoff_psymtab_to_symtab;
- /* Set up language for the pst. Native ecoff has every header file in
- a separate FDR. deduce_language_from_filename will return
- language_unknown for a header file, which is not what we want.
+ /* Set up language for the pst.
+ The language from the FDR is used if it is unambigious (e.g. cfront
+ with native cc and g++ will set the language to C).
+ Otherwise we have to deduce the language from the filename.
+ Native ecoff has every header file in a separate FDR, so
+ deduce_language_from_filename will return language_unknown for
+ a header file, which is not what we want.
But the FDRs for the header files are after the FDR for the source
file, so we can assign the language of the source file to the
following header files. Then we save the language in the private
pst data so that we can reuse it when building symtabs. */
prev_language = psymtab_language;
- psymtab_language = deduce_language_from_filename (fdr_name (fh));
+
+ switch (fh->lang)
+ {
+ case langCplusplusV2:
+ psymtab_language = language_cplus;
+ break;
+ default:
+ psymtab_language = deduce_language_from_filename (fdr_name (fh));
+ break;
+ }
if (psymtab_language == language_unknown)
psymtab_language = prev_language;
PST_PRIVATE (pst)->pst_language = psymtab_language;
switch (psh->st)
{
case stProc:
+ case stStaticProc:
class = LOC_BLOCK;
break;
case stLabel:
/* Now scan the FDRs for dependencies */
for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++)
{
- int s_id0 = 0;
fh = f_idx + ecoff_data (cur_bfd)->fdr;
pst = fdr_to_pst[f_idx].pst;
if (fh->crfd <= 1)
continue;
- if (fh->cpd == 0)
- { /* If there are no functions defined here ... */
- /* ...then presumably a .h file: drop reverse depends .h->.c */
- for (; s_id0 < fh->crfd; s_id0++)
- {
- RFDT rh;
-
- (*swap_rfd_in) (cur_bfd,
- ((char *) ecoff_data (cur_bfd)->external_rfd
- + (fh->rfdBase + s_id0) * external_rfd_size),
- &rh);
- if (rh == f_idx)
- {
- s_id0++; /* Skip self-dependency */
- break;
- }
- }
- }
+ /* Skip the first file indirect entry as it is a self dependency
+ for source files or a reverse .h -> .c dependency for header files. */
pst->number_of_dependencies = 0;
pst->dependencies =
((struct partial_symtab **)
obstack_alloc (&objfile->psymbol_obstack,
- ((fh->crfd - s_id0)
+ ((fh->crfd - 1)
* sizeof (struct partial_symtab *))));
- for (s_idx = s_id0; s_idx < fh->crfd; s_idx++)
+ for (s_idx = 1; s_idx < fh->crfd; s_idx++)
{
RFDT rh;
continue;
}
- /* Skip self-dependency. */
+ /* Skip self dependencies of header files. */
if (rh == f_idx)
continue;
= ecoff_backend (cur_bfd)->external_pdr_size;
void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
= ecoff_backend (cur_bfd)->swap_sym_in;
- void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR))
- = ecoff_backend (cur_bfd)->swap_sym_out;
void (* const swap_pdr_in) PARAMS ((bfd *, PTR, PDR *))
= ecoff_backend (cur_bfd)->swap_pdr_in;
int i;
char *pdr_ptr;
char *pdr_end;
int first_pdr;
- unsigned long first_off;
+ unsigned long first_off = 0;
/* This symbol table contains stabs-in-ecoff entries. */
SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
SYMBOL_CLASS (s) = LOC_CONST;
SYMBOL_TYPE (s) = builtin_type_void;
- SYMBOL_VALUE (s) = (int) e;
+ SYMBOL_VALUE (s) = (long) e;
add_symbol_to_list (s, &local_symbols);
}
}
psymtab_language = st->language;
lines = LINETABLE (st);
- pending_list = PST_PRIVATE (pst)->pending_list;
- if (pending_list == 0)
- {
- pending_list = ((struct mips_pending **)
- xzalloc (ecoff_data (cur_bfd)->symbolic_header.ifdMax
- * sizeof (struct mips_pending *)));
- PST_PRIVATE (pst)->pending_list = pending_list;
- }
/* Get a new lexical context */
(ecoff_data (cur_bfd)->external_aux
+ fh->iauxBase),
sym_ptr, fh->fBigendian);
- /* FIXME: We must swap the modified symbol back out,
- although we would rather not. See parse_symbol. */
- (*swap_sym_out) (cur_bfd, &sh, sym_ptr);
sym_ptr += c * external_sym_size;
}
Return value says how many aux symbols we ate. */
static int
-cross_ref (ax, tpp, type_code, pname, bigend, sym_name)
+cross_ref (fd, ax, tpp, type_code, pname, bigend, sym_name)
+ int fd;
union aux_ext *ax;
struct type **tpp;
enum type_code type_code; /* Use to alloc new type if none is found. */
RNDXR rn[1];
unsigned int rf;
int result = 1;
+ FDR *fh;
+ char *esh;
+ SYMR sh;
+ int xref_fd;
+ struct mips_pending *pend;
+
+ *tpp = (struct type *)NULL;
ecoff_swap_rndx_in (bigend, &ax->a_rndx, rn);
rf = rn->rfd;
}
+ /* mips cc uses a rf of -1 for opaque struct definitions.
+ Set TYPE_FLAG_STUB for these types so that check_stub_type will
+ resolve them if the struct gets defined in another compilation unit. */
if (rf == -1)
{
- /* Ooops */
*pname = "<undefined>";
+ *tpp = init_type (type_code, 0, 0, (char *) NULL, current_objfile);
+ TYPE_FLAGS (*tpp) |= TYPE_FLAG_STUB;
+ return result;
}
- else
+
+ /* mips cc uses an escaped rn->index of 0 for struct return types
+ of procedures that were compiled without -g. These will always remain
+ undefined. */
+ if (rn->rfd == 0xfff && rn->index == 0)
{
- /*
- * Find the relative file descriptor and the symbol in it
- */
- FDR *fh = get_rfd (cur_fd, rf);
- char *esh;
- SYMR sh;
- struct type *t;
+ *pname = "<undefined>";
+ return result;
+ }
- if (rn->index >= fh->csym)
- {
- /* File indirect entry is corrupt. */
- *tpp = (struct type *)NULL;
- *pname = "<illegal>";
- complain (&bad_rfd_entry_complaint,
- sym_name, fh - ecoff_data (cur_bfd)->fdr, rn->index);
- return result;
- }
+ /* Find the relative file descriptor and the symbol in it. */
+ fh = get_rfd (fd, rf);
+ xref_fd = fh - ecoff_data (cur_bfd)->fdr;
- /* If we have processed this symbol then we left a forwarding
- pointer to the corresponding GDB symbol. If not, we`ll put
- it in a list of pending symbols, to be processed later when
- the file will be. In any event, we collect the name for the
- type here. Which is why we made a first pass at strings. */
-
- esh = ((char *) ecoff_data (cur_bfd)->external_sym
- + ((fh->isymBase + rn->index)
- * ecoff_backend (cur_bfd)->external_sym_size));
- (*ecoff_backend (cur_bfd)->swap_sym_in) (cur_bfd, esh, &sh);
-
- /* Careful, we might be looking at .o files */
- if (sh.iss == 0)
- *pname = "<undefined>";
- else if (rn->rfd == 0xfff && rn->index == 0)
- /* For structs, unions and enums, rn->rfd is 0xfff and the index
- is a relative symbol number for the type, but an index of 0
- seems to mean that we don't know. This is said to fix a problem
- with "info func opendir" on an SGI showing
- "struct BSDopendir.c *BSDopendir();". */
- {
- *tpp = (struct type *)NULL;
- *pname = "<unknown>";
- return result;
- }
- else if ((sh.st != stBlock && sh.st != stTypedef && sh.st != stParsed)
- || sh.sc != scInfo)
+ if (rn->index >= fh->csym)
+ {
+ /* File indirect entry is corrupt. */
+ *pname = "<illegal>";
+ complain (&bad_rfd_entry_complaint,
+ sym_name, xref_fd, rn->index);
+ return result;
+ }
+
+ /* If we have processed this symbol then we left a forwarding
+ pointer to the type in the pending list. If not, we`ll put
+ it in a list of pending types, to be processed later when
+ the file will be. In any event, we collect the name for the
+ type here. */
+
+ esh = ((char *) ecoff_data (cur_bfd)->external_sym
+ + ((fh->isymBase + rn->index)
+ * ecoff_backend (cur_bfd)->external_sym_size));
+ (*ecoff_backend (cur_bfd)->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))
+ {
+ /* File indirect entry is corrupt. */
+ *pname = "<illegal>";
+ complain (&bad_rfd_entry_complaint,
+ sym_name, xref_fd, rn->index);
+ return result;
+ }
+
+ *pname = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss;
+
+ pend = is_pending_symbol (fh, esh);
+ if (pend)
+ *tpp = pend->t;
+ else
+ {
+ /* We have not yet seen this type. */
+
+ if (sh.iss == 0 && sh.st == stTypedef)
{
- /* File indirect entry is corrupt. */
- *tpp = (struct type *)NULL;
- *pname = "<illegal>";
- complain (&bad_rfd_entry_complaint,
- sym_name, fh - ecoff_data (cur_bfd)->fdr, rn->index);
+ TIR tir;
+
+ /* alpha cc puts out a stTypedef with a sh.iss of zero for
+ two cases:
+ a) forward declarations of structs/unions/enums which are not
+ defined in this compilation unit.
+ 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.
+ The forward references are not entered in the pending list and
+ in the symbol table. */
+
+ ecoff_swap_tir_in (bigend,
+ &(ecoff_data (cur_bfd)->external_aux
+ + fh->iauxBase + sh.index)->a_ti,
+ &tir);
+ if (tir.tq0 != tqNil)
+ complain (&illegal_forward_tq0_complaint, sym_name);
+ switch (tir.bt)
+ {
+ case btVoid:
+ *tpp = init_type (type_code, 0, 0, (char *) NULL,
+ current_objfile);
+ *pname = "<undefined>";
+ break;
+
+ case btStruct:
+ case btUnion:
+ case btEnum:
+ cross_ref (xref_fd,
+ (ecoff_data (cur_bfd)->external_aux
+ + fh->iauxBase + sh.index + 1),
+ tpp, type_code, pname,
+ fh->fBigendian, sym_name);
+ break;
+
+ default:
+ complain (&illegal_forward_bt_complaint, tir.bt, sym_name);
+ *tpp = init_type (type_code, 0, 0, (char *) NULL,
+ current_objfile);
+ break;
+ }
return result;
}
- else
- *pname = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss;
-
- /* Have we parsed it ? */
- if (sh.value != 0 && sh.st == stParsed)
+ else if (sh.st == stTypedef)
{
- t = (struct type *) sh.value;
- *tpp = t;
+ /* Parse the type for a normal 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. But 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,
+ (ecoff_data (cur_bfd)->external_aux
+ + fh->iauxBase + sh.index),
+ (int *)NULL,
+ fh->fBigendian,
+ (ecoff_data (cur_bfd)->ss
+ + fh->issBase + sh.iss));
}
else
{
- /* Avoid duplicates */
- struct mips_pending *p = is_pending_symbol (fh, esh);
- if (p)
- *tpp = p->t;
- else
- {
- *tpp = init_type (type_code, 0, 0, (char *) NULL,
- (struct objfile *) NULL);
- add_pending (fh, esh, *tpp);
- }
+ /* Cross reference to a struct/union/enum which is defined
+ in another file in the same compilation unit but that file
+ has not been parsed yet.
+ Initialize the type only, it will be filled in when
+ it's definition is parsed. */
+ *tpp = init_type (type_code, 0, 0, (char *) NULL, current_objfile);
}
+ add_pending (fh, esh, *tpp);
}
/* We used one auxent normally, two if we got a "next one" rf. */
{
struct symbol *s;
struct symtab *st;
- struct block *b, *b0;
+ struct block *b, *b0 = NULL;
sigtramp_address = -1;
SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
SYMBOL_CLASS (s) = LOC_BLOCK;
SYMBOL_TYPE (s) = init_type (TYPE_CODE_FUNC, 4, 0, (char *) NULL,
- (struct objfile *) NULL);
+ st->objfile);
TYPE_TARGET_TYPE (SYMBOL_TYPE (s)) = builtin_type_void;
/* Need a block to allocate MIPS_EFI_SYMBOL_NAME in */
current_objfile = st->objfile; /* Keep new_symbol happy */
s = new_symbol (MIPS_EFI_SYMBOL_NAME);
- SYMBOL_VALUE (s) = (int) e;
+ SYMBOL_VALUE (s) = (long) e;
SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
SYMBOL_CLASS (s) = LOC_CONST;
SYMBOL_TYPE (s) = builtin_type_void;