aboutsummaryrefslogtreecommitdiff
path: root/gas/config/obj-ecoff.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config/obj-ecoff.c')
-rw-r--r--gas/config/obj-ecoff.c230
1 files changed, 143 insertions, 87 deletions
diff --git a/gas/config/obj-ecoff.c b/gas/config/obj-ecoff.c
index 1e29ab8..d0a9b04 100644
--- a/gas/config/obj-ecoff.c
+++ b/gas/config/obj-ecoff.c
@@ -831,6 +831,7 @@ typedef struct scope {
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 */
@@ -1393,7 +1394,8 @@ static alloc_info_t alloc_counts[ (int)alloc_type_last ];
/* 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
@@ -1561,6 +1563,11 @@ obj_read_begin_hook ()
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. */
@@ -1683,6 +1690,10 @@ add_ecoff_symbol (str, type, storage, sym_value, value, indx)
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;
@@ -2194,7 +2205,7 @@ add_procedure (func)
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);
@@ -2428,7 +2439,10 @@ obj_ecoff_begin (ignore)
*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++;
}
/* Parse .bend directives which have a label as the first argument
@@ -2440,7 +2454,7 @@ obj_ecoff_bend (ignore)
{
char *name;
char name_end;
- symbolS *begin;
+ symbolS *endsym;
if (cur_file_ptr == (efdr_t *) NULL)
{
@@ -2460,21 +2474,21 @@ obj_ecoff_bend (ignore)
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++;
}
/* COFF debugging information is provided as a series of directives
@@ -2601,15 +2615,8 @@ obj_ecoff_scl (ignore)
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 ();
}
@@ -2674,6 +2681,7 @@ obj_ecoff_type (ignore)
{
long val;
tq_t *tq_ptr;
+ tq_t *tq_shft;
if (coff_sym_name == (char *) NULL)
{
@@ -2687,27 +2695,31 @@ obj_ecoff_type (ignore)
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
@@ -2716,9 +2728,12 @@ obj_ecoff_type (ignore)
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 ();
}
@@ -2796,6 +2811,7 @@ static void
obj_ecoff_endef (ignore)
int ignore;
{
+ char *name;
symint_t indx;
localsym_t *sym;
@@ -2807,6 +2823,19 @@ obj_ecoff_endef (ignore)
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)
{
@@ -2863,7 +2892,7 @@ obj_ecoff_endef (ignore)
{
if (coff_tag == (char *) NULL)
{
- as_warn ("No tag specified for %s", coff_sym_name);
+ as_warn ("No tag specified for %s", name);
return;
}
@@ -2908,8 +2937,8 @@ obj_ecoff_endef (ignore)
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;
@@ -2927,7 +2956,7 @@ obj_ecoff_endef (ignore)
}
/* Add the symbol. */
- sym = add_ecoff_symbol (coff_sym_name,
+ sym = add_ecoff_symbol (name,
coff_symbol_type,
coff_storage_class,
coff_sym_value,
@@ -2938,7 +2967,7 @@ obj_ecoff_endef (ignore)
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;
@@ -2998,7 +3027,7 @@ obj_ecoff_end (ignore)
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);
@@ -3189,18 +3218,10 @@ obj_ecoff_loc (ignore)
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 ();
@@ -3599,7 +3620,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
}
else if (delta <= -7)
{
- *bufptr++ = 0x0f + (9 << 4);
+ *bufptr++ = 0x0f + (-7 << 4);
delta += 7;
}
else
@@ -3745,6 +3766,7 @@ ecoff_build_symbols (buf,
for (; sym_ptr < sym_end; sym_ptr++)
{
int local;
+ symbolS *as_sym;
forward_t *f;
know (sym_ptr->file_ptr == fil_ptr);
@@ -3757,26 +3779,65 @@ ecoff_build_symbols (buf,
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);
}
@@ -3817,12 +3878,13 @@ ecoff_build_symbols (buf,
/* 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));
}
}
@@ -3855,9 +3917,9 @@ ecoff_build_symbols (buf,
}
/* 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;
@@ -3866,7 +3928,7 @@ ecoff_build_symbols (buf,
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))
@@ -3875,7 +3937,7 @@ ecoff_build_symbols (buf,
(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;
}
@@ -4245,6 +4307,8 @@ ecoff_frob_symbol (sym)
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;
@@ -4261,6 +4325,21 @@ ecoff_frob_file ()
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. */
@@ -4283,35 +4362,12 @@ ecoff_frob_file ()
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;