/* Read a symbol table in ECOFF format (Third-Eye).
- Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993 Free Software
- Foundation, Inc.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994
+ 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
at Cygnus Support.
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 *));
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));
+
static char *
mdebug_next_symbol_text PARAMS ((void));
\f
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:
+ /* 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)
{
case stNil:
add_symbol (s, b);
/* Type could be missing in a number of cases */
- if (sh->sc == scUndefined || sh->sc == scNil ||
- sh->index == 0xfffff)
+ if (sh->sc == scUndefined || sh->sc == scNil)
SYMBOL_TYPE (s) = builtin_type_int; /* undefined? */
else
SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name);
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);
}
else
t = pend->t;
- /* Alpha cc unnamed structs do not get a tag name. */
- if (sh->iss == 0)
+ /* Do not set the tag name if it is a compiler generated tag name
+ (.Fxx or .xxfake or empty) for unnamed struct/union/enums.
+ Alpha cc puts out an sh->iss of zero for those. */
+ if (sh->iss == 0 || name[0] == '.' || name[0] == '\0')
TYPE_TAG_NAME (t) = NULL;
else
TYPE_TAG_NAME (t) = obconcat (¤t_objfile->symbol_obstack,
if (type_code == TYPE_CODE_ENUM)
{
/* This is a non-empty enum. */
+
+ /* DEC c89 has the number of enumerators in the sh.value field,
+ not the type length, so we have to compensate for that
+ 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))
+ TYPE_LENGTH (t) = TARGET_INT_BIT / HOST_CHAR_BIT;
for (ext_tsym = ext_sh + external_sym_size;
;
ext_tsym += external_sym_size)
f->bitsize = 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 */
/* Typedefs for forward declarations and opaque structs from alpha cc
are handled by cross_ref, skip them. */
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;
struct type *tp = 0;
enum type_code type_code = TYPE_CODE_UNDEF;
+ /* Handle undefined types, they have indexNil. */
+ if (aux_index == indexNil)
+ return builtin_type_int;
+
/* Handle corrupt aux indices. */
if (aux_index >= (debug_info->fdr + fd)->caux)
{
if (tp == (struct type *) NULL)
tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile);
+ /* DEC c89 produces cross references to qualified aggregate types,
+ dereference them. */
+ while (TYPE_CODE (tp) == TYPE_CODE_PTR
+ || TYPE_CODE (tp) == TYPE_CODE_ARRAY)
+ tp = tp->target_type;
+
/* Make sure that TYPE_CODE(tp) has an expected type code.
Any type may be returned from cross_ref if file indirect entries
are corrupted. */
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 *, unsigned long,
+ struct partial_symtab *));
static void
-parse_procedure (pr, search_symtab, first_off)
+parse_procedure (pr, search_symtab, first_off, pst)
PDR *pr;
struct symtab *search_symtab;
unsigned long first_off;
+ struct partial_symtab *pst;
{
struct symbol *s, *i;
struct block *b;
if (pr->isym == -1)
{
/* Static procedure at address pr->adr. Sigh. */
+ /* FIXME-32x64. assuming pr->adr fits in long. */
complain (&pdr_static_symbol_complaint, (unsigned long) pr->adr);
return;
}
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;
+ e->pdr.adr += pst->textlow - first_off;
/* Correct incorrect setjmp procedure descriptor from the library
to make backtrace through setjmp work. */
e->pdr.regmask = 0x80000000;
e->pdr.regoffset = -4;
}
-
- /* Fake PC_REGNUM for alpha __sigtramp so that read_next_frame_reg
- will use the saved user pc from the sigcontext. */
- if (STREQ (sh_name, "__sigtramp"))
- e->pdr.pcreg = PC_REGNUM;
- /* Make the same patch for Irix. */
- if (STREQ (sh_name, "_sigtramp"))
- e->pdr.pcreg = PC_REGNUM;
}
}
+/* 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;
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:
/* 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 *));
+
static void
-parse_lines (fh, pr, lt, maxlines)
+parse_lines (fh, pr, lt, maxlines, pst)
FDR *fh;
PDR *pr;
struct linetable *lt;
int maxlines;
+ struct partial_symtab *pst;
{
unsigned char *base;
int j, k;
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++)
halt = base + fh->cbLine;
base += pr->cbLineOffset;
- adr = fh->adr + pr->adr - first_off;
+ adr = pst->textlow + pr->adr - first_off;
+
l = adr >> 2; /* in words */
for (lineno = pr->lnLow; base < halt; )
{
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;
}
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. */
switch (ext_in->asym.st)
{
case stProc:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
break;
case stStaticProc:
ms_type = mst_file_text;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
break;
case stGlobal:
- if (ext_in->asym.sc == scData
+ if (ext_in->asym.sc == scCommon)
+ {
+ /* The value of a common symbol is its size, not its address.
+ Ignore it. */
+ continue;
+ }
+ else if (ext_in->asym.sc == scData
|| ext_in->asym.sc == scSData
- || ext_in->asym.sc == scRData)
- ms_type = mst_data;
+ || ext_in->asym.sc == scRData
+ || ext_in->asym.sc == scPData
+ || ext_in->asym.sc == scXData)
+ {
+ ms_type = mst_data;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ }
else
- ms_type = mst_bss;
+ {
+ ms_type = mst_bss;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_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 == scText
+ || ext_in->asym.sc == scInit
+ || ext_in->asym.sc == scFini)
+ {
+ ms_type = mst_file_text;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ }
else if (ext_in->asym.sc == scData
|| ext_in->asym.sc == scSData
- || ext_in->asym.sc == scRData)
- ms_type = mst_data;
+ || ext_in->asym.sc == scRData
+ || ext_in->asym.sc == scPData
+ || ext_in->asym.sc == scXData)
+ {
+ ms_type = mst_file_data;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ }
else
- ms_type = mst_bss;
+ {
+ ms_type = mst_file_bss;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ }
break;
case stLocal:
/* The alpha has the section start addresses in stLocal symbols
ms_type = mst_unknown;
complain (&unknown_ext_complaint, name);
}
- prim_record_minimal_symbol (name, ext_in->asym.value, ms_type, objfile);
+ prim_record_minimal_symbol (name, svalue, ms_type, objfile);
}
/* Pass 3 over files, over local syms: fill in static symbols */
{
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;
+ long 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,
+ objfile);
+ }
+ procaddr = sh.value;
isym = AUX_GET_ISYM (fh->fBigendian,
(debug_info->external_aux
if (sh.st == stEnd)
{
long 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 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,
+ objfile);
+ break;
+
+ default:
+ 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,
+ objfile);
+ break;
+ }
+ }
continue;
}
#define SET_NAMESTRING() \
name = debug_info->ss + fh->issBase + sh.iss;
+ switch (sh.sc)
+ {
+ case scText:
+ /* 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;
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, 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,
+ sh.value, psymtab_language, objfile);
+ else
+ ADD_PSYMBOL_TO_LIST (name, strlen (name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ objfile->static_psymbols,
+ 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 (sh.sc == scData
+ || sh.sc == scSData
+ || sh.sc == scRData
+ || sh.sc == scPData
+ || sh.sc == scXData)
+ prim_record_minimal_symbol_and_info (name, sh.value,
+ mst_file_data, NULL,
+ SECT_OFF_DATA,
+ 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,
+ 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;
sh.value,
psymtab_language, objfile);
}
+ handle_psymbol_enumerators (objfile, fh, sh.st);
+
/* Skip over the block */
new_sdx = sh.index;
if (new_sdx <= cur_sdx)
enum address_class class;
SYMR *psh;
char *name;
+ CORE_ADDR svalue;
if (ext_ptr->ifd != f_idx)
abort ();
if (psh->sc == scUndefined || psh->sc == scNil)
continue;
+ svalue = psh->value;
+ switch (psh->sc)
+ {
+ case scText:
+ 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;
ADD_PSYMBOL_ADDR_TO_LIST (name, strlen (name),
VAR_NAMESPACE, class,
objfile->global_psymbols,
- (CORE_ADDR) psh->value,
+ svalue,
psymtab_language, objfile);
}
}
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)
+ struct objfile *objfile;
+ FDR *fh;
+ int stype;
+{
+ 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. */
+ (*swap_sym_in) (cur_bfd, ext_sym, &sh);
+ if (sh.st != stMember)
+ return;
+
+ if (sh.index == indexNil)
+ break;
+ ecoff_swap_tir_in (fh->fBigendian,
+ &(debug_info->external_aux
+ + fh->iauxBase + sh.index)->a_ti,
+ &tir);
+ if ((tir.bt != btNil && tir.bt != btVoid) || 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,
+ psymtab_language, objfile);
+ ext_sym += external_sym_size;
+ }
+}
static char *
mdebug_next_symbol_text ()
add_symbol_to_list (s, &local_symbols);
}
}
- else if (sh.st == stLabel && sh.index != indexNil)
+ else if (sh.st == stLabel)
{
- /* Handle encoded stab line number. */
- record_line (current_subfile, sh.index, valu);
+ if (sh.index == indexNil)
+ {
+ /* This is what the gcc2_compiled and __gnu_compiled_*
+ show up as. So don't complain. */
+ ;
+ }
+ else
+ /* Handle encoded stab line number. */
+ 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
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;
first_off = pr.adr;
first_pdr = 0;
}
- parse_procedure (&pr, st, first_off);
+ parse_procedure (&pr, st, first_off, pst);
}
}
else
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;
(*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;
}
pdr_ptr += external_pdr_size, pdr_in++)
(*swap_pdr_in) (cur_bfd, pdr_ptr, pdr_in);
- parse_lines (fh, pr_block, lines, maxlines);
+ parse_lines (fh, pr_block, lines, maxlines, pst);
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, pr_block->adr, 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;
+ ecoff_swap_tir_in (fh->fBigendian, &ax->a_ti, &tir);
+ if (tir.bt != btStruct && tir.bt != btUnion && tir.bt != btEnum)
+ return 0;
+
+ ax++;
+ ecoff_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).
(*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.sc != scCommon || sh.st != stBlock))
{
/* 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;
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.
+ 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. */
CORE_ADDR adr;
int last;
{
+ /* DEC c89 sometimes produces zero linenos which confuse gdb.
+ Change them to something sensible. */
+ if (lineno == 0)
+ lineno = 1;
if (last == 0)
last = -2; /* make sure we record first line */
/* 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 */
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)
+ if (!bfd_get_section_contents (abfd, sec, buf, (file_ptr) 0,
+ swap->external_hdr_size))
perror_with_name (bfd_get_filename (abfd));
info = ((struct ecoff_debug_info *)
xzalloc (sizeof (struct mips_extra_func_info)));
e->numargs = 0; /* the kernel thinks otherwise */
- /* align_longword(sigcontext + SIGFRAME) */
- e->pdr.frameoffset = 0x150;
+ e->pdr.frameoffset = 32;
e->pdr.framereg = SP_REGNUM;
- /* read_next_frame_reg provides the true pc at the time of signal */
+ /* Note that setting pcreg is no longer strictly necessary as
+ mips_frame_saved_pc is now aware of signal handler frames. */
e->pdr.pcreg = PC_REGNUM;
e->pdr.regmask = -2;
- e->pdr.regoffset = -(41 * sizeof (int));
+ /* Offset to saved r31, in the sigtramp case the saved registers
+ are above the frame in the sigcontext.
+ We have 4 alignment bytes, 12 bytes for onstack, mask and pc,
+ 32 * 4 bytes for the general registers, 12 bytes for mdhi, mdlo, ownedfp
+ and 32 * 4 bytes for the floating point registers. */
+ e->pdr.regoffset = 4 + 12 + 31 * 4;
e->pdr.fregmask = -1;
- e->pdr.fregoffset = -(7 * sizeof (int));
+ /* Offset to saved f30 (first saved *double* register). */
+ e->pdr.fregoffset = 4 + 12 + 32 * 4 + 12 + 30 * 4;
e->pdr.isym = (long) s;
e->pdr.adr = sigtramp_address;