/* Read a symbol table in ECOFF format (Third-Eye).
- Copyright 1986, 87, 89, 90, 91, 92, 93, 94, 95, 96, 1997
+ 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
#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
+
+/* 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)
+
\f
/* We put a pointer to this structure in the read_symtab_private field
of the psymtab. */
#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 */
class = LOC_STATIC;
b = top_stack->cur_block;
s = new_symbol (name);
- if (sh->sc == scCommon || sh->sc == scSCommon)
+ 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
add_symbol (s, b);
/* Type could be missing if file is compiled without debugging info. */
- if (sh->sc == scUndefined || sh->sc == scSUndefined
+ if (SC_IS_UNDEF(sh->sc)
|| sh->sc == scNil || sh->index == indexNil)
SYMBOL_TYPE (s) = nodebug_var_symbol_type;
else
SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
SYMBOL_CLASS (s) = LOC_BLOCK;
/* Type of the return value */
- if (sh->sc == scUndefined || sh->sc == scSUndefined || sh->sc == scNil)
+ 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);
if (STREQ(name, "malloc") && t->code == TYPE_CODE_VOID)
{
- /* I don't know why, but, at least under Linux/Alpha,
+ /* 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
add_block (b, top_stack->cur_st);
/* Not if we only have partial info */
- if (sh->sc == scUndefined || sh->sc == scSUndefined || 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 && sh->sc != scSCommon)
+ if (sh->sc != scInfo && !SC_IS_COMMON(sh->sc))
goto case_stBlock_code; /* Lexical block */
type_code = TYPE_CODE_UNDEF; /* We have a type. */
break;
case stEnd: /* end (of anything) */
- if (sh->sc == scInfo || sh->sc == scCommon || sh->sc == scSCommon)
+ if (sh->sc == scInfo || SC_IS_COMMON(sh->sc))
{
/* Finished with type */
top_stack->cur_type = 0;
}
/* Reading .o files */
- if (es->asym.sc == scUndefined || es->asym.sc == scSUndefined
- || es->asym.sc == scNil)
+ if (SC_IS_UNDEF(es->asym.sc) || es->asym.sc == scNil)
{
char *what;
switch (es->asym.st)
case stLabel:
/* Global common symbols are resolved by the runtime loader,
ignore them. */
- if (es->asym.sc == scCommon || es->asym.sc == scSCommon)
+ if (SC_IS_COMMON(es->asym.sc))
break;
/* Note that the case of a symbol with indexNil must be handled
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;
- CORE_ADDR svalue = ext_in->asym.value;
+ /* 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 == scSUndefined
- || ext_in->asym.sc == scNil)
- continue;
- name = debug_info->ssext + ext_in->asym.iss;
- 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 == scCommon || ext_in->asym.sc == scSCommon)
- {
- /* The value of a common symbol is its size, not its address.
- Ignore it. */
+ 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;
- }
- else if (ext_in->asym.sc == scData
- || ext_in->asym.sc == scSData
- || 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;
- 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
- || 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
- || 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_file_bss;
- svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
- }
- 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);
- }
- prim_record_minimal_symbol (name, svalue, ms_type, objfile);
- }
+ /* 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++)
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,
}
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)\
#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 == scSUndefined
- || sh.sc == scNil
+ if (SC_IS_UNDEF(sh.sc) || sh.sc == scNil
|| (sh.index == indexNil
&& (sh.st != stStatic || sh.sc == scAbs)))
{
continue;
case stStatic: /* Variable */
- if (sh.sc == scData
- || sh.sc == scSData
- || sh.sc == scRData
- || sh.sc == scPData
- || sh.sc == scXData)
+ if (SC_IS_DATA (sh.sc))
prim_record_minimal_symbol_and_info (name, sh.value,
mst_file_data, NULL,
SECT_OFF_DATA,
/* Do not create a partial symbol for cc unnamed aggregates
and gcc empty aggregates. */
if ((sh.sc == scInfo
- || sh.sc == scCommon || sh.sc == scSCommon)
+ || SC_IS_COMMON(sh.sc))
&& sh.iss != 0
&& sh.index != cur_sdx + 2)
{
psh = &ext_ptr->asym;
/* Do not add undefined symbols to the partial symbol table. */
- if (psh->sc == scUndefined || psh->sc == scSUndefined
- || psh->sc == scNil)
+ if (SC_IS_UNDEF(psh->sc) || psh->sc == scNil)
continue;
svalue = psh->value;
case stGlobal:
/* Global common symbols are resolved by the runtime loader,
ignore them. */
- if (psh->sc == scCommon || psh->sc == scSCommon)
+ if (SC_IS_COMMON(psh->sc))
continue;
class = LOC_STATIC;
|| (sh.st != stBlock && sh.st != stTypedef && sh.st != stIndirect
&& sh.st != stStruct && sh.st != stUnion
&& sh.st != stEnum))
- && (sh.st != stBlock || (sh.sc != scCommon && sh.sc != scSCommon)))
+ && (sh.st != stBlock || !SC_IS_COMMON(sh.sc)))
{
/* File indirect entry is corrupt. */
*pname = "<illegal>";