/* Read a symbol table in ECOFF format (Third-Eye).
- Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
Free Software Foundation, Inc.
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 {
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};
/* 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 *));
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 *
shrink_linetable PARAMS ((struct linetable *));
static void
-handle_psymbol_enumerators PARAMS ((struct objfile *, FDR *, int));
+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 */
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);
if (sh->sc == scUndefined || 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 Linux/Alpha,
+ 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*
+ */
+ t = t->pointer_type;
+ }
+ }
b = top_stack->cur_block;
if (sh->st == stProc)
{
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. */
+ if (tsym.index == indexNil
+ || (tsym.index == 0 && sh->value == 0))
type_code = TYPE_CODE_ENUM;
else
{
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;
;
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 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. */
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 mdebug_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
definition, and only the type-qualifiers fully identify
them. We'll make the same effort at sharing. */
/* 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;
}
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
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 *, CORE_ADDR,
struct partial_symtab *));
static void
-parse_procedure (pr, search_symtab, first_off, pst)
+parse_procedure (pr, search_symtab, lowest_pdr_addr, pst)
PDR *pr;
struct symtab *search_symtab;
- unsigned long first_off;
+ CORE_ADDR lowest_pdr_addr;
struct partial_symtab *pst;
{
struct symbol *s, *i;
e = (struct mips_extra_func_info *) SYMBOL_VALUE (i);
e->pdr = *pr;
e->pdr.isym = (long) s;
- e->pdr.adr += pst->textlow - first_off;
+ e->pdr.adr += pst->textlow - lowest_pdr_addr;
/* Correct incorrect setjmp procedure descriptor from the library
to make backtrace through setjmp work. */
with that and do not need to reorder our linetables */
static void parse_lines PARAMS ((FDR *, PDR *, struct linetable *, int,
- struct partial_symtab *));
+ struct partial_symtab *, CORE_ADDR));
static void
-parse_lines (fh, pr, lt, maxlines, pst)
+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;
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 = pst->textlow + 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 */
#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"
symbol table, and the MAIN__ symbol via the minimal
symbol table. */
if (sh.st == stProc)
- ADD_PSYMBOL_TO_LIST (name, strlen (name),
+ add_psymbol_to_list (name, strlen (name),
VAR_NAMESPACE, LOC_BLOCK,
- objfile->global_psymbols,
- sh.value, psymtab_language, objfile);
+ &objfile->global_psymbols,
+ sh.value, 0, psymtab_language, objfile);
else
- ADD_PSYMBOL_TO_LIST (name, strlen (name),
+ add_psymbol_to_list (name, strlen (name),
VAR_NAMESPACE, LOC_BLOCK,
- objfile->static_psymbols,
- sh.value, psymtab_language, objfile);
+ &objfile->static_psymbols,
+ sh.value, 0, psymtab_language, objfile);
/* Skip over procedure to next one. */
if (sh.index >= hdr->iauxMax)
&& 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,
+ sh.value, 0,
psymtab_language, objfile);
}
- handle_psymbol_enumerators (objfile, fh, sh.st);
+ handle_psymbol_enumerators (objfile, fh, sh.st, sh.value);
/* Skip over the block */
new_sdx = sh.index;
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, sh.value,
+ 0, psymtab_language, objfile);
skip:
cur_sdx++; /* Go to next file symbol */
}
break;
}
name = debug_info->ssext + psh->iss;
- ADD_PSYMBOL_ADDR_TO_LIST (name, strlen (name),
- VAR_NAMESPACE, class,
- objfile->global_psymbols,
- svalue,
- 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)
{
all the the enum constants to the partial symbol table. */
static void
-handle_psymbol_enumerators (objfile, fh, stype)
+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 *))
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. */
+ is a plain btNil or btVoid.
+ Alpha cc -migrate enums are recognized by a zero index and
+ a zero symbol value. */
(*swap_sym_in) (cur_bfd, ext_sym, &sh);
if (sh.st != stMember)
return;
- if (sh.index == indexNil)
+ if (sh.index == indexNil
+ || (sh.index == 0 && svalue == 0))
break;
(*debug_swap->swap_tir_in) (fh->fBigendian,
&(debug_info->external_aux
/* Note that the value doesn't matter for enum constants
in psymtabs, just in symtabs. */
- ADD_PSYMBOL_TO_LIST (name, strlen (name),
+ add_psymbol_to_list (name, strlen (name),
VAR_NAMESPACE, LOC_CONST,
- objfile->static_psymbols, 0,
- psymtab_language, objfile);
+ &objfile->static_psymbols, 0,
+ 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. */
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.
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, pst);
+
+ pdr_in = pr_block;
+ pdr_in_end = pdr_in + fh->cpd;
+ for (; pdr_in < pdr_in_end; pdr_in++)
+ parse_procedure (pdr_in, st, lowest_pdr_addr, pst);
+
+ do_cleanups (old_chain);
}
}
else
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, pst);
+ 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, pst);
+ parse_procedure (pdr_in, 0, lowest_pdr_addr, pst);
do_cleanups (old_chain);
}
}
/* 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)
{
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. Irix5 cc uses a stIndirect symbol for this.
+ 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. */
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;
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;
/* 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 ()
BLOCK_SYM (b, BLOCK_NSYMS (b)++) = s;
}
+#endif /* TM_MIPS_H */
+
void
_initialize_mdebugread ()
{