information we generate. The gas symbol will be NULL if this is
only a debugging symbol. */
typedef struct localsym {
+ const char *name; /* symbol name */
symbolS *as_sym; /* symbol as seen by gas */
struct efdr *file_ptr; /* file pointer */
struct ecoff_proc *proc_ptr; /* proc pointer */
/* Various statics. */
static efdr_t *cur_file_ptr = (efdr_t *) 0; /* current file desc. header */
static proc_t *cur_proc_ptr = (proc_t *) 0; /* current procedure header */
-static thead_t *cur_tag_head = (thead_t *)0; /* current tag head */
+static thead_t *top_tag_head = (thead_t *) 0; /* top level tag head */
+static thead_t *cur_tag_head = (thead_t *) 0; /* current tag head */
#ifdef ECOFF_DEBUG
static int debug = 0; /* trace functions */
#endif
tag_hash = hash_new ();
if (tag_hash == (struct hash_control *) NULL)
as_fatal ("Can't create hash table");
+ top_tag_head = allocate_thead ();
+ top_tag_head->first_tag = (tag_t *) NULL;
+ top_tag_head->free = (thead_t *) NULL;
+ top_tag_head->prev = cur_tag_head;
+ cur_tag_head = top_tag_head;
}
/* This function is called when a symbol is created. */
psym = &vp->last->datum->sym[ vp->objects_last_page++ ];
+ if (str == (const char *) NULL && sym_value != (symbolS *) NULL)
+ psym->name = S_GET_NAME (sym_value);
+ else
+ psym->name = str;
psym->as_sym = sym_value;
if (sym_value != (symbolS *) NULL)
sym_value->ecoff_symbol = 1;
new_proc_ptr->pdr.iline = -1;
/* Push the start of the function. */
- new_proc_ptr->sym = add_ecoff_symbol (func, st_Proc, sc_Text,
+ new_proc_ptr->sym = add_ecoff_symbol ((const char *) NULL, st_Proc, sc_Text,
symbol_find_or_make (func),
(symint_t) 0, (symint_t) 0);
*input_line_pointer = name_end;
- demand_empty_rest_of_line ();
+ /* The line number follows, but we don't use it. */
+ while (! is_end_of_line[*input_line_pointer])
+ input_line_pointer++;
+ input_line_pointer++;
}
\f
/* Parse .bend directives which have a label as the first argument
{
char *name;
char name_end;
- symbolS *begin;
+ symbolS *endsym;
if (cur_file_ptr == (efdr_t *) NULL)
{
name_end = get_symbol_end ();
/* The value is the distance between the .bend directive and the
- corresponding symbol. We create a fake symbol to hold the
- current location, and put in the offset when we write out the
- symbol. */
- begin = symbol_find (name);
- if (begin == (symbolS *) NULL)
+ corresponding symbol. We fill in the offset when we write out
+ the symbol. */
+ endsym = symbol_find (name);
+ if (endsym == (symbolS *) NULL)
as_warn (".bend directive names unknown symbol");
else
- (void) add_ecoff_symbol (name, st_End, sc_Text,
- symbol_new ("L0\001", now_seg,
- frag_now_fix (), frag_now),
+ (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, endsym,
(symint_t) 0, (symint_t) 0);
*input_line_pointer = name_end;
- demand_empty_rest_of_line ();
+ /* The line number follows, but we don't use it. */
+ while (! is_end_of_line[*input_line_pointer])
+ input_line_pointer++;
+ input_line_pointer++;
}
\f
/* COFF debugging information is provided as a series of directives
val = get_absolute_expression ();
- /* If the symbol is a static or external, we have already gotten the
- appropriate type and class, so make sure we don't override those
- values. This is needed because there are some type and classes
- that are not in COFF, such as short data, etc. */
- if (coff_symbol_type == st_Nil)
- {
- coff_symbol_type = map_coff_sym_type[val];
- coff_storage_class = map_coff_storage[val];
- }
+ coff_symbol_type = map_coff_sym_type[val];
+ coff_storage_class = map_coff_storage[val];
demand_empty_rest_of_line ();
}
{
long val;
tq_t *tq_ptr;
+ tq_t *tq_shft;
if (coff_sym_name == (char *) NULL)
{
coff_type.orig_type = BTYPE (val);
coff_type.basic_type = map_coff_types[coff_type.orig_type];
- tq_ptr = &coff_type.type_qualifiers[0];
+ tq_ptr = &coff_type.type_qualifiers[N_TQ];
while (val &~ N_BTMASK)
{
- if (tq_ptr == &coff_type.type_qualifiers[N_TQ])
+ if (tq_ptr == &coff_type.type_qualifiers[0])
{
as_warn ("Too derived values in .type argument");
break;
}
if (ISPTR (val))
- *tq_ptr++ = tq_Ptr;
+ *--tq_ptr = tq_Ptr;
else if (ISFCN (val))
- *tq_ptr++ = tq_Proc;
+ *--tq_ptr = tq_Proc;
else if (ISARY (val))
- *tq_ptr++ = tq_Array;
+ *--tq_ptr = tq_Array;
else
as_fatal ("Unrecognized .type argument");
val = DECREF (val);
}
- if (tq_ptr != &coff_type.type_qualifiers[0] && tq_ptr[-1] == tq_Proc)
+ tq_shft = &coff_type.type_qualifiers[0];
+ while (tq_ptr != &coff_type.type_qualifiers[N_TQ])
+ *tq_shft++ = *tq_ptr++;
+
+ if (tq_shft != &coff_type.type_qualifiers[0] && tq_shft[-1] == tq_Proc)
{
/* If this is a function, ignore it, so that we don't get two
entries (one from the .ent, and one for the .def that
MIPS knows what reason, we must strip off the function type
at this point. */
coff_is_function = 1;
- tq_ptr[-1] = tq_Nil;
+ tq_shft[-1] = tq_Nil;
}
+ while (tq_shft != &coff_type.type_qualifiers[N_TQ])
+ *tq_shft++ = tq_Nil;
+
demand_empty_rest_of_line ();
}
obj_ecoff_endef (ignore)
int ignore;
{
+ char *name;
symint_t indx;
localsym_t *sym;
return;
}
+ name = coff_sym_name;
+ coff_sym_name = (char *) NULL;
+
+ /* If the symbol is a static or external, we have already gotten the
+ appropriate type and class, so make sure we don't override those
+ values. This is needed because there are some type and classes
+ that are not in COFF, such as short data, etc. */
+ if (coff_sym_value != (symbolS *) NULL)
+ {
+ coff_symbol_type = st_Nil;
+ coff_storage_class = sc_Nil;
+ }
+
coff_type.extra_sizes = coff_tag != (char *) NULL;
if (coff_type.num_dims > 0)
{
{
if (coff_tag == (char *) NULL)
{
- as_warn ("No tag specified for %s", coff_sym_name);
+ as_warn ("No tag specified for %s", name);
return;
}
name which is always ".eos". This needs to be done last, so
that any error reporting above gives the correct name. */
case st_End:
- free (coff_sym_name);
- coff_sym_name = (char *) NULL;
+ free (name);
+ name = (char *) NULL;
coff_value = 0;
coff_inside_enumeration = 0;
break;
}
/* Add the symbol. */
- sym = add_ecoff_symbol (coff_sym_name,
+ sym = add_ecoff_symbol (name,
coff_symbol_type,
coff_storage_class,
coff_sym_value,
if (coff_symbol_type == st_Block)
{
/* Create or update the tag information. */
- tag_t *tag_ptr = get_tag (coff_sym_name,
+ tag_t *tag_ptr = get_tag (name,
sym,
coff_type.basic_type);
forward_t **pf;
if (ent == (symbolS *) NULL)
as_warn (".end directive names unknown symbol");
else
- (void) add_ecoff_symbol (name, st_End, sc_Text,
+ (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text,
symbol_new ("L0\001", now_seg,
frag_now_fix (), frag_now),
(symint_t) 0, (symint_t) 0);
return;
}
- /* FIXME: .loc directives look like ``.loc 1 4'' where the first
- number is the file index and the second number is the line
- number. Unfortunately, do_scrub_next_char removes the space,
- producing ``.loc 14''. Urrrk. I'm afraid I'll break something
- if I change do_scrub_next_char, so instead we do this gross hack.
- Note that file_index is one less than the value in the .loc,
- because we adjusted it by one in the call to add_file. This
- actually won't work in the unfortunate circumstance of the same
- file appearing twice with different indices with different
- numbers of digits, which is possible. */
+ /* Skip the file number. */
+ SKIP_WHITESPACE ();
+ get_absolute_expression ();
SKIP_WHITESPACE ();
- input_line_pointer += 1 + (cur_file_ptr->file_index + 1) / 10;
list = allocate_lineno_list ();
}
else if (delta <= -7)
{
- *bufptr++ = 0x0f + (9 << 4);
+ *bufptr++ = 0x0f + (-7 << 4);
delta += 7;
}
else
for (; sym_ptr < sym_end; sym_ptr++)
{
int local;
+ symbolS *as_sym;
forward_t *f;
know (sym_ptr->file_ptr == fil_ptr);
both if the local provides additional debugging
information for the external). */
local = 1;
- if (sym_ptr->as_sym != (symbolS *) NULL)
+ as_sym = sym_ptr->as_sym;
+ if (as_sym != (symbolS *) NULL)
{
- sym_ptr->ecoff_sym.value = S_GET_VALUE (sym_ptr->as_sym);
+ sym_ptr->ecoff_sym.value = S_GET_VALUE (as_sym);
+
+ /* Get the type and storage class based on where
+ the symbol actually wound up. */
+ if (sym_ptr->ecoff_sym.st == st_Nil
+ && sym_ptr->ecoff_sym.sc == sc_Nil
+ && ! MIPS_IS_STAB (&sym_ptr->ecoff_sym))
+ {
+ st_t st;
+ sc_t sc;
+
+ if (S_IS_EXTERNAL (as_sym)
+ || ! S_IS_DEFINED (as_sym))
+ st = st_Global;
+ else if (S_GET_SEGMENT (as_sym) == text_section)
+ st = st_Label;
+ else
+ st = st_Static;
+
+ if (! S_IS_DEFINED (as_sym))
+ sc = sc_Undefined;
+ else if (S_IS_COMMON (as_sym))
+ sc = sc_Common;
+ else if (S_GET_SEGMENT (as_sym) == text_section)
+ sc = sc_Text;
+ else if (S_GET_SEGMENT (as_sym) == data_section)
+ sc = sc_Data;
+ else if (S_GET_SEGMENT (as_sym) == bss_section)
+ sc = sc_Bss;
+ else
+ abort ();
+
+ sym_ptr->ecoff_sym.st = (int) st;
+ sym_ptr->ecoff_sym.sc = (int) sc;
+ }
/* This is just an external symbol if it is
- outside a procedure and it has a type. */
- if ((S_IS_EXTERNAL (sym_ptr->as_sym)
- || ! S_IS_DEFINED (sym_ptr->as_sym))
+ outside a procedure and it has a type.
+ FIXME: g++ will generate symbols which have
+ different names in the debugging information
+ than the actual symbol. Should we handle
+ them here? */
+ if ((S_IS_EXTERNAL (as_sym)
+ || ! S_IS_DEFINED (as_sym))
&& sym_ptr->proc_ptr == (proc_t *) NULL
&& sym_ptr->ecoff_sym.st != (int) st_Nil)
local = 0;
/* If an st_end symbol has an associated gas
- symbol, then it is a fake created for a .bend
- or .end directive. */
+ symbol, then it is a local label created for
+ a .bend or .end directive. */
if (local && sym_ptr->ecoff_sym.st != st_End)
sym_ptr->ecoff_sym.iss =
add_string (&fil_ptr->strings,
fil_ptr->str_hash,
- S_GET_NAME (sym_ptr->as_sym),
+ sym_ptr->name,
(shash_t **) NULL);
}
/* The value of the symbol marking the end of a
procedure or block is the size of the
procedure or block. */
- if (begin_type == st_Proc || begin_type == st_Block)
+ if ((begin_type == st_Proc || begin_type == st_Block)
+ && sym_ptr->ecoff_sym.sc != (int) sc_Info)
{
- know (sym_ptr->as_sym != (symbolS *) NULL);
+ know (as_sym != (symbolS *) NULL);
know (begin_ptr->as_sym != (symbolS *) NULL);
sym_ptr->ecoff_sym.value =
- (S_GET_VALUE (sym_ptr->as_sym)
+ (S_GET_VALUE (as_sym)
- S_GET_VALUE (begin_ptr->as_sym));
}
}
}
/* If this is an external symbol, swap it out. */
- if (sym_ptr->as_sym != (symbolS *) NULL
- && (S_IS_EXTERNAL (sym_ptr->as_sym)
- || ! S_IS_DEFINED (sym_ptr->as_sym)))
+ if (as_sym != (symbolS *) NULL
+ && (S_IS_EXTERNAL (as_sym)
+ || ! S_IS_DEFINED (as_sym)))
{
EXTR ext;
ext.ifd = fil_ptr->file_index;
ext.asym.iss = add_string (ext_strings,
ext_str_hash,
- S_GET_NAME (sym_ptr->as_sym),
+ S_GET_NAME (as_sym),
(shash_t **) NULL);
if (*extbufend - (char *) ext_out
< sizeof (struct ext_ext))
(char *) ext_out,
sizeof (struct ext_ext)));
ecoff_swap_ext_out (stdoutput, &ext, ext_out);
- ecoff_set_sym_index (sym_ptr->as_sym->bsym, iext);
+ ecoff_set_sym_index (as_sym->bsym, iext);
++ext_out;
++iext;
}
void
ecoff_frob_file ()
{
+ tag_t *ptag;
+ tag_t *ptag_next;
efdr_t *fil_ptr;
efdr_t *hold_file_ptr;
proc_t * hold_proc_ptr;
struct hash_control *ext_str_hash;
char *set;
+ /* Handle any top level tags. */
+ for (ptag = top_tag_head->first_tag;
+ ptag != (tag_t *) NULL;
+ ptag = ptag_next)
+ {
+ if (ptag->forward_ref != (forward_t *) NULL)
+ add_unknown_tag (ptag);
+
+ ptag_next = ptag->same_block;
+ ptag->hash_ptr->tag_ptr = ptag->same_name;
+ free_tag (ptag);
+ }
+
+ free_thead (top_tag_head);
+
/* Output an ending symbol for all the files. We have to do this
here for the last file, so we may as well do it for all of the
files. */
cur_proc_ptr = (proc_t *) NULL;
for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
{
- st_t st;
- sc_t sc;
-
if (sym->ecoff_symbol
|| sym->ecoff_file == (efdr_t *) NULL)
continue;
- if (S_IS_EXTERNAL (sym) || ! S_IS_DEFINED (sym))
- st = st_Global;
- else if (S_GET_SEGMENT (sym) == text_section)
- st = st_Label;
- else
- st = st_Static;
-
- if (! S_IS_DEFINED (sym))
- sc = sc_Undefined;
- else if (S_IS_COMMON (sym))
- sc = sc_Common;
- else if (S_GET_SEGMENT (sym) == text_section)
- sc = sc_Text;
- else if (S_GET_SEGMENT (sym) == data_section)
- sc = sc_Data;
- else if (S_GET_SEGMENT (sym) == bss_section)
- sc = sc_Bss;
- else
- abort ();
-
cur_file_ptr = sym->ecoff_file;
- add_ecoff_symbol (S_GET_NAME (sym), st, sc, sym,
+ add_ecoff_symbol ((const char *) NULL, st_Nil, sc_Nil, sym,
S_GET_VALUE (sym), indexNil);
}
cur_proc_ptr = hold_proc_ptr;