aboutsummaryrefslogtreecommitdiff
path: root/gas/config/obj-ecoff.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1993-04-01 02:14:29 +0000
committerIan Lance Taylor <ian@airs.com>1993-04-01 02:14:29 +0000
commit670a50ebf65de85eab0ccf22da227e218f704037 (patch)
tree1c276cc2005d44c84d9dfa5d4b1698ecb7facabc /gas/config/obj-ecoff.c
parent8155a95d965478c30f59cbc63a7a2bef01ef884a (diff)
downloadgdb-670a50ebf65de85eab0ccf22da227e218f704037.zip
gdb-670a50ebf65de85eab0ccf22da227e218f704037.tar.gz
gdb-670a50ebf65de85eab0ccf22da227e218f704037.tar.bz2
* subsegs.c (subseg_new): Set output_section of new section.
* as.c (perform_an_assemly_pass): Don't set output_section here. * expr.c (expr_part, expr): Turn off section assertions for ECOFF, since it has additional sections. * read.c (s_lcomm): For MIPS ECOFF, put small objects in .sbss, not bss_section. * config/obj-ecoff.h (TARGET_SYMBOL_FIELDS): Added ecoff_undefined field. * config/obj-ecoff.c (obj_symbol_new_hook): Initialize ecoff_undefined field. (add_file): If using stabs, just output a stabs symbol rather than creating a new fdr. (obj_ecoff_begin, obj_ecoff_bend): Ignore line number by reading it with get_absolute_expression, rather than skipping it by hand. (obj_ecoff_loc): If using stabs, just output a stabs symbol rather than ECOFF line number information. (obj_ecoff_stab): Accept non-zero values for stabs line number. (ecoff_build_symbols): Set ifilesym correctly. Set storage class to small, undefined and/or readonly sections if appropriate. Don't output symbol names containing \001 characters. (ecoff_frob_file): Make sure at least one fdr is output. * config/tc-mips.h: Define TC_MIPS. * config/tc-mips.c (g_switch_value): New static variable. (md_assemble): Set gp size of output BFD. (gp_reference): New function; returns 1 if expression can be accesssed via gp. Always returns 0 if not using ECOFF. (macro_build): Convert BFD_RELOC_LO16 to BFD_RELOC_MIPS_GPREL if possible. (macro): Generate sequences using gp if possible. (md_parse_option): Ignore -EL and -EB. Parse -G. (md_apply_fix): Added BFD_RELOC_MIPS_GPREL to ignored case. (s_change_sec): Handle .rdata and .sdata for ECOFF. (s_extern): Mark symbol as external. Set ecoff_undefined field.
Diffstat (limited to 'gas/config/obj-ecoff.c')
-rw-r--r--gas/config/obj-ecoff.c286
1 files changed, 186 insertions, 100 deletions
diff --git a/gas/config/obj-ecoff.c b/gas/config/obj-ecoff.c
index d0a9b04..5677ee1 100644
--- a/gas/config/obj-ecoff.c
+++ b/gas/config/obj-ecoff.c
@@ -30,6 +30,8 @@
#include "aout/stab_gnu.h"
#include "../bfd/libecoff.h"
+#include <ctype.h>
+
/* Why isn't this in coff/sym.h? */
#define ST_RFDESCAPE 0xfff
@@ -1578,6 +1580,7 @@ obj_symbol_new_hook (symbolP)
{
symbolP->ecoff_file = cur_file_ptr;
symbolP->ecoff_symbol = 0;
+ symbolP->ecoff_undefined = 0;
}
/* Add a page to a varray object. */
@@ -2203,6 +2206,8 @@ add_procedure (func)
new_proc_ptr->pdr.isym = -1;
new_proc_ptr->pdr.iline = -1;
+ new_proc_ptr->pdr.lnLow = -1;
+ new_proc_ptr->pdr.lnHigh = -1;
/* Push the start of the function. */
new_proc_ptr->sym = add_ecoff_symbol ((const char *) NULL, st_Proc, sc_Text,
@@ -2261,6 +2266,17 @@ add_file (file_name, indx)
}
}
+ /* If we're creating stabs, then we don't actually make a new FDR.
+ Instead, we just create a stabs symbol. */
+ if (stabs_seen)
+ {
+ (void) add_ecoff_symbol (file_name, st_Nil, sc_Nil,
+ symbol_new ("L0\001", now_seg,
+ frag_now_fix (), frag_now),
+ 0, MIPS_MARK_STAB (N_SOL));
+ return;
+ }
+
first_ch = *file_name;
/* See if the file has already been created. */
@@ -2440,9 +2456,8 @@ obj_ecoff_begin (ignore)
*input_line_pointer = name_end;
/* The line number follows, but we don't use it. */
- while (! is_end_of_line[*input_line_pointer])
- input_line_pointer++;
- input_line_pointer++;
+ (void) get_absolute_expression ();
+ demand_empty_rest_of_line ();
}
/* Parse .bend directives which have a label as the first argument
@@ -2486,9 +2501,8 @@ obj_ecoff_bend (ignore)
*input_line_pointer = name_end;
/* The line number follows, but we don't use it. */
- while (! is_end_of_line[*input_line_pointer])
- input_line_pointer++;
- input_line_pointer++;
+ (void) get_absolute_expression ();
+ demand_empty_rest_of_line ();
}
/* COFF debugging information is provided as a series of directives
@@ -3201,7 +3215,6 @@ static void
obj_ecoff_loc (ignore)
int ignore;
{
- char buf[20];
lineno_list_t *list;
if (cur_file_ptr == (efdr_t *) NULL)
@@ -3223,6 +3236,17 @@ obj_ecoff_loc (ignore)
get_absolute_expression ();
SKIP_WHITESPACE ();
+ /* If we're building stabs, then output a special label rather than
+ ECOFF line number info. */
+ if (stabs_seen)
+ {
+ (void) add_ecoff_symbol ((char *) NULL, st_Label, sc_Text,
+ symbol_new ("L0\001", now_seg,
+ frag_now_fix (), frag_now),
+ 0, get_absolute_expression ());
+ return;
+ }
+
list = allocate_lineno_list ();
list->next = (lineno_list_t *) NULL;
@@ -3395,17 +3419,14 @@ obj_ecoff_stab (type)
value = 0;
st = st_Label;
- sc = sc_Undefined;
+ sc = sc_Text;
}
else
{
- /* Skip 0, */
- if (get_absolute_expression () != 0)
- {
- as_warn ("Bad .stab%c directive (expected 0)", type);
- demand_empty_rest_of_line ();
- return;
- }
+ /* The next number is sometimes the line number of the
+ declaration. We have nowhere to put it, so we just ignore
+ it. */
+ (void) get_absolute_expression ();
SKIP_WHITESPACE ();
if (*input_line_pointer++ != ',')
@@ -3442,17 +3463,8 @@ obj_ecoff_stab (type)
sym = symbol_find_or_make (name);
- /* Traditionally, N_LBRAC and N_RBRAC are *not* relocated. */
- if (code == N_LBRAC || code == N_RBRAC)
- {
- sc = sc_Nil;
- st = st_Nil;
- }
- else
- {
- sc = sc_Undefined;
- st = st_Nil;
- }
+ sc = sc_Nil;
+ st = st_Nil;
value = 0;
*input_line_pointer = name_end;
@@ -3512,6 +3524,7 @@ ecoff_longword_adjust (buf, bufend, offset, bufptrptr)
add = 4 - (offset & 3);
if (*bufend - (*buf + offset) < add)
(void) ecoff_add_bytes (buf, bufend, *buf + offset, add);
+ memset (*buf + offset, 0, add);
offset += add;
if (bufptrptr != (char **) NULL)
*bufptrptr = *buf + offset;
@@ -3536,6 +3549,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
proc_t *proc;
long c;
long iline;
+ long totcount;
bufptr = *buf + offset;
@@ -3544,11 +3558,28 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
last = (lineno_list_t *) NULL;
c = offset;
iline = 0;
+ totcount = 0;
for (l = first_lineno; l != (lineno_list_t *) NULL; l = l->next)
{
long count;
long delta;
- int didone;
+
+ /* Get the offset to the memory address of the next line number
+ (in words). Do this first, so that we can skip ahead to the
+ next useful line number entry. */
+ if (l->next == (lineno_list_t *) NULL)
+ count = 0;
+ else
+ {
+ count = ((l->next->frag->fr_address + l->next->paddr
+ - (l->frag->fr_address + l->paddr))
+ >> 2);
+ if (count <= 0)
+ {
+ /* Don't change last, so we still get the right delta. */
+ continue;
+ }
+ }
if (l->file != file || l->proc != proc)
{
@@ -3557,11 +3588,11 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
if (l->file != file && file != (efdr_t *) NULL)
{
file->fdr.cbLine = c - file->fdr.cbLineOffset;
- file->fdr.cline = iline - file->fdr.ilineBase;
+ /* The cline field is ill-documented. This is a guess
+ at the right value. */
+ file->fdr.cline = totcount + count;
}
- c = ecoff_longword_adjust (buf, bufend, c, &bufptr);
-
if (l->file != file)
{
file = l->file;
@@ -3573,33 +3604,18 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
proc = l->proc;
if (proc != (proc_t *) NULL)
{
- /* The iline field is ill-documented. This is a
- guess at the right value. */
- proc->pdr.iline = l->frag->fr_address + l->paddr;
proc->pdr.lnLow = l->lineno;
proc->pdr.cbLineOffset = c - file->fdr.cbLineOffset;
+ /* The iline field is ill-documented. This is a
+ guess at the right value. */
+ proc->pdr.iline = totcount;
}
}
last = (lineno_list_t *) NULL;
}
- /* Get the offset to the memory address of the next line number
- (in words). */
- if (l->next == (lineno_list_t *) NULL)
- count = 0;
- else
- {
- count = (((l->next->frag->fr_address + l->next->paddr
- - (l->frag->fr_address + l->paddr))
- >> 2)
- - 1);
- if (count < 0)
- {
- /* Don't change last, so we still get the right delta. */
- continue;
- }
- }
+ totcount += count;
/* Get the offset to this line number. */
if (last == (lineno_list_t *) NULL)
@@ -3607,40 +3623,30 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
else
delta = l->lineno - last->lineno;
- /* We can only adjust the address by 16 words at a time. */
- didone = 0;
- while (count > 0x10)
+ /* Put in the offset to this line number. */
+ while (delta != 0)
{
- if (bufptr >= *bufend)
- bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
- if (delta >= 7)
- {
- *bufptr++ = 0x0f + (7 << 4);
- delta -= 7;
- }
- else if (delta <= -7)
+ int setcount;
+
+ /* 1 is added to each count read. */
+ --count;
+ /* We can only adjust the word count by up to 15 words at a
+ time. */
+ if (count <= 0x0f)
{
- *bufptr++ = 0x0f + (-7 << 4);
- delta += 7;
+ setcount = count;
+ count = 0;
}
else
{
- *bufptr++ = 0x0f + (delta << 4);
- delta = 0;
+ setcount = 0x0f;
+ count -= 0x0f;
}
- ++c;
- count -= 0x10;
- didone = 1;
- }
-
- /* Put in the offset to this line number. */
- while (delta != 0 || ! didone)
- {
if (delta >= -7 && delta <= 7)
{
if (bufptr >= *bufend)
bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
- *bufptr++ = count + (delta << 4);
+ *bufptr++ = setcount + (delta << 4);
delta = 0;
++c;
}
@@ -3650,7 +3656,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
if (*bufend - bufptr < 3)
bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 3);
- *bufptr++ = count + (8 << 4);
+ *bufptr++ = setcount + (8 << 4);
if (delta < -0x8000)
{
set = -0x8000;
@@ -3670,8 +3676,26 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
*bufptr++ = set & 0xffff;
c += 3;
}
- count = 0;
- didone = 1;
+ }
+
+ /* Finish adjusting the count. */
+ while (count > 0)
+ {
+ if (bufptr >= *bufend)
+ bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
+ /* 1 is added to each count read. */
+ --count;
+ if (count > 0x0f)
+ {
+ *bufptr++ = 0x0f;
+ count -= 0x0f;
+ }
+ else
+ {
+ *bufptr++ = count;
+ count = 0;
+ }
+ ++c;
}
++iline;
@@ -3683,7 +3707,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
if (file != (efdr_t *) NULL)
{
file->fdr.cbLine = c - file->fdr.cbLineOffset;
- file->fdr.cline = iline - file->fdr.ilineBase;
+ file->fdr.cline = totcount;
}
c = ecoff_longword_adjust (buf, bufend, c, &bufptr);
@@ -3736,8 +3760,6 @@ ecoff_build_symbols (buf,
efdr_t *fil_ptr;
efdr_t *fil_end;
- ifilesym = isym;
-
if (file_link->next == (vlinks_t *) NULL)
fil_cnt = file_desc.objects_last_page;
else
@@ -3749,6 +3771,7 @@ ecoff_build_symbols (buf,
vlinks_t *sym_link;
fil_ptr->fdr.isymBase = isym;
+ ifilesym = isym;
for (sym_link = fil_ptr->symbols.first;
sym_link != (vlinks_t *) NULL;
sym_link = sym_link->next)
@@ -3782,35 +3805,79 @@ ecoff_build_symbols (buf,
as_sym = sym_ptr->as_sym;
if (as_sym != (symbolS *) NULL)
{
- sym_ptr->ecoff_sym.value = S_GET_VALUE (as_sym);
+ symint_t indx;
+
+ /* The value of a block start symbol is the
+ offset from the start of the procedure. For
+ other symbols we just use the gas value. */
+ if (sym_ptr->ecoff_sym.st == (int) st_Block
+ && sym_ptr->ecoff_sym.sc == (int) sc_Text)
+ {
+ know (sym_ptr->proc_ptr != (proc_t *) NULL);
+ sym_ptr->ecoff_sym.value =
+ (S_GET_VALUE (as_sym)
+ - S_GET_VALUE (sym_ptr->proc_ptr->sym->as_sym));
+ }
+ else
+ sym_ptr->ecoff_sym.value = S_GET_VALUE (as_sym);
/* Get the type and storage class based on where
- the symbol actually wound up. */
+ the symbol actually wound up. Traditionally,
+ N_LBRAC and N_RBRAC are *not* relocated. */
+ indx = sym_ptr->ecoff_sym.index;
if (sym_ptr->ecoff_sym.st == st_Nil
&& sym_ptr->ecoff_sym.sc == sc_Nil
- && ! MIPS_IS_STAB (&sym_ptr->ecoff_sym))
+ && (! MIPS_IS_STAB (&sym_ptr->ecoff_sym)
+ || ((MIPS_UNMARK_STAB (indx) != N_LBRAC)
+ && (MIPS_UNMARK_STAB (indx) != N_RBRAC))))
{
+ segT seg;
+ const char *segname;
st_t st;
sc_t sc;
+ seg = S_GET_SEGMENT (as_sym);
+ segname = segment_name (seg);
+
if (S_IS_EXTERNAL (as_sym)
|| ! S_IS_DEFINED (as_sym))
st = st_Global;
- else if (S_GET_SEGMENT (as_sym) == text_section)
+ else if (seg == text_section)
st = st_Label;
else
st = st_Static;
- if (! S_IS_DEFINED (as_sym))
- sc = sc_Undefined;
+ if (! S_IS_DEFINED (as_sym)
+ || as_sym->ecoff_undefined)
+ {
+ if (S_GET_VALUE (as_sym) > 0
+ && (S_GET_VALUE (as_sym)
+ <= bfd_get_gp_size (stdoutput)))
+ sc = sc_SUndefined;
+ else
+ sc = sc_Undefined;
+ }
else if (S_IS_COMMON (as_sym))
- sc = sc_Common;
- else if (S_GET_SEGMENT (as_sym) == text_section)
+ {
+ if (S_GET_VALUE (as_sym) > 0
+ && (S_GET_VALUE (as_sym)
+ <= bfd_get_gp_size (stdoutput)))
+ sc = sc_SCommon;
+ else
+ sc = sc_Common;
+ }
+ else if (seg == text_section)
sc = sc_Text;
- else if (S_GET_SEGMENT (as_sym) == data_section)
+ else if (seg == data_section)
sc = sc_Data;
- else if (S_GET_SEGMENT (as_sym) == bss_section)
+ else if (strcmp (segname, ".rdata") == 0)
+ sc = sc_RData;
+ else if (strcmp (segname, ".sdata") == 0)
+ sc = sc_SData;
+ else if (seg == bss_section)
sc = sc_Bss;
+ else if (strcmp (segname, ".sbss") == 0)
+ sc = sc_SBss;
else
abort ();
@@ -3827,13 +3894,17 @@ ecoff_build_symbols (buf,
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)
+ && sym_ptr->ecoff_sym.st != (int) st_Nil
+ && ! MIPS_IS_STAB (&sym_ptr->ecoff_sym))
local = 0;
/* If an st_end symbol has an associated gas
symbol, then it is a local label created for
- a .bend or .end directive. */
- if (local && sym_ptr->ecoff_sym.st != st_End)
+ a .bend or .end directive. Stabs line
+ numbers will have \001 in the names. */
+ if (local
+ && sym_ptr->ecoff_sym.st != st_End
+ && strchr (sym_ptr->name, '\001') == 0)
sym_ptr->ecoff_sym.iss =
add_string (&fil_ptr->strings,
fil_ptr->str_hash,
@@ -3876,10 +3947,11 @@ 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)
- && sym_ptr->ecoff_sym.sc != (int) sc_Info)
+ procedure is the size of the procedure. The
+ value of the symbol marking the end of a
+ block is the offset from the start of the
+ procedure to the block. */
+ if (begin_type == st_Proc)
{
know (as_sym != (symbolS *) NULL);
know (begin_ptr->as_sym != (symbolS *) NULL);
@@ -3887,6 +3959,15 @@ ecoff_build_symbols (buf,
(S_GET_VALUE (as_sym)
- S_GET_VALUE (begin_ptr->as_sym));
}
+ else if (begin_type == st_Block
+ && sym_ptr->ecoff_sym.sc != (int) sc_Info)
+ {
+ know (as_sym != (symbolS *) NULL);
+ know (sym_ptr->proc_ptr != (proc_t *) NULL);
+ sym_ptr->ecoff_sym.value =
+ (S_GET_VALUE (as_sym)
+ - S_GET_VALUE (sym_ptr->proc_ptr->sym->as_sym));
+ }
}
for (f = sym_ptr->forward_ref;
@@ -3908,18 +3989,21 @@ ecoff_build_symbols (buf,
ecoff_swap_sym_out (stdoutput, &sym_ptr->ecoff_sym,
sym_out);
++sym_out;
+
sym_ptr->sym_index = isym;
- ++isym;
if (sym_ptr->proc_ptr != (proc_t *) NULL
&& sym_ptr->proc_ptr->sym == sym_ptr)
sym_ptr->proc_ptr->pdr.isym = isym - ifilesym;
+
+ ++isym;
}
/* If this is an external symbol, swap it out. */
if (as_sym != (symbolS *) NULL
&& (S_IS_EXTERNAL (as_sym)
- || ! S_IS_DEFINED (as_sym)))
+ || ! S_IS_DEFINED (as_sym))
+ && ! MIPS_IS_STAB (&sym_ptr->ecoff_sym))
{
EXTR ext;
@@ -4325,6 +4409,10 @@ ecoff_frob_file ()
struct hash_control *ext_str_hash;
char *set;
+ /* Make sure we have a file. */
+ if (first_file == (efdr_t *) NULL)
+ add_file ((const char *) NULL, 0);
+
/* Handle any top level tags. */
for (ptag = top_tag_head->first_tag;
ptag != (tag_t *) NULL;
@@ -4477,8 +4565,6 @@ ecoff_frob_file ()
#undef SET
- /* FIXME: set the gp value. */
-
/* FIXME: set the register masks. */
ecoff_data (stdoutput)->raw_size = offset;