aboutsummaryrefslogtreecommitdiff
path: root/gas/read.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1993-10-06 17:31:31 +0000
committerIan Lance Taylor <ian@airs.com>1993-10-06 17:31:31 +0000
commit80aab57939a0e22d4614fa759433c1713f047033 (patch)
tree3a3afbb30c1b9aca4b1ce9c5c957a511b303e96a /gas/read.c
parent9978cd4dc9134185ff8be094db9d74ca2b545713 (diff)
downloadgdb-80aab57939a0e22d4614fa759433c1713f047033.zip
gdb-80aab57939a0e22d4614fa759433c1713f047033.tar.gz
gdb-80aab57939a0e22d4614fa759433c1713f047033.tar.bz2
Changes to let cons handle bignums like general expressions.
* expr.h (expressionS): New field X_unsigned. * expr.c (operand): Initialize X_unsigned to 1. Set it to 0 for unary minus case. (expr) Fix typo resultP to right if missing operand. Set X_unsigned to 1 when building new expression. * read.c (potable): Make "octa" and "quad" call cons, not big_cons. (cons): Handle bignums. If given an O_constant (small integer) to fill a big space, turn it into a bignum. (parse_bitfield_cons): Set X_unsigned field. (bignum_low, bignum_limit, bignum_high, grow_bignum, big_cons): Removed. * read.h (big_cons): Remove prototype. * symbols.c (resolve_symbol_value): Don't give a warning if a symbol in expr_section can not be resolved. (S_SET_VALUE): Clear X_unsigned. * write.c (write_object_file): If resolve_symbol_value failed on a symbol we are writing out, give a warning. * config/tc-h8500.c (parse_reglist): Set X_unsigned. * config/tc-hppa.c (md_pseudo_table): Change "octa" and "quad" to call pa_cons, not pa_big_cons. (pa_big_cons): Remove. * config/tc-hppa.h (pa_big_cons): Remove declaration. * config/tc-i960.c (md_pseudo_table): Change "quad" to call cons, not big_cons.
Diffstat (limited to 'gas/read.c')
-rw-r--r--gas/read.c752
1 files changed, 303 insertions, 449 deletions
diff --git a/gas/read.c b/gas/read.c
index 762d3d8..f741f46 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -133,12 +133,6 @@ char is_end_of_line[256] =
static char *buffer; /* 1st char of each buffer of lines is here. */
static char *buffer_limit; /*->1 + last char in buffer. */
-static char *bignum_low; /* Lowest char of bignum. */
-static char *bignum_limit; /* 1st illegal address of bignum. */
-static char *bignum_high; /* Highest char of bignum. */
-/* May point to (bignum_start-1). */
-/* Never >= bignum_limit. */
-
int target_big_endian;
static char *old_buffer; /* JF a hack */
@@ -161,10 +155,7 @@ static char *demand_copy_string PARAMS ((int *lenP));
int is_it_end_of_statement PARAMS ((void));
static segT get_segmented_expression PARAMS ((expressionS *expP));
static segT get_known_segmented_expression PARAMS ((expressionS * expP));
-static void grow_bignum PARAMS ((void));
static void pobegin PARAMS ((void));
-
-extern int listing;
void
@@ -180,10 +171,6 @@ read_begin ()
obstack_begin (&notes, 5090);
obstack_begin (&cond_obstack, 990);
-#define BIGNUM_BEGIN_SIZE (16)
- bignum_low = xmalloc ((long) BIGNUM_BEGIN_SIZE);
- bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE;
-
/* Use machine dependent syntax */
for (p = line_separator_chars; *p; p++)
is_end_of_line[(unsigned char) *p] = 1;
@@ -241,11 +228,11 @@ static const pseudo_typeS potable[] =
{"long", cons, 4},
{"lsym", s_lsym, 0},
{"nolist", listing_list, 0}, /* Turn listing off */
- {"octa", big_cons, 16},
+ {"octa", cons, 16},
{"org", s_org, 0},
{"psize", listing_psize, 0}, /* set paper size */
/* print */
- {"quad", big_cons, 8},
+ {"quad", cons, 8},
{"sbttl", listing_title, 1}, /* Subtitle of listing */
/* scl */
/* sect */
@@ -281,7 +268,7 @@ pobegin ()
for (pop = md_pseudo_table; pop->poc_name; pop++)
{
errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
- if (errtxt && *errtxt)
+ if (errtxt)
{
as_fatal ("error constructing md pseudo-op table");
} /* on error */
@@ -291,7 +278,7 @@ pobegin ()
for (pop = obj_pseudo_table; pop->poc_name; pop++)
{
errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
- if (errtxt && *errtxt)
+ if (errtxt)
{
if (!strcmp (errtxt, "exists"))
{
@@ -311,7 +298,7 @@ pobegin ()
for (pop = potable; pop->poc_name; pop++)
{
errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
- if (errtxt && *errtxt)
+ if (errtxt)
{
if (!strcmp (errtxt, "exists"))
{
@@ -1529,7 +1516,7 @@ pseudo_set (symbolP)
*
* CONStruct more frag of .bytes, or .words etc.
* Should need_pass_2 be 1 then emit no frag(s).
- * This understands EXPRESSIONS, as opposed to big_cons().
+ * This understands EXPRESSIONS.
*
* Bug (?)
*
@@ -1608,6 +1595,7 @@ emit_expr (exp, nbytes)
{
operatorT op;
register char *p;
+ valueT extra_digit = 0;
/* Don't do anything if we are going to make another pass. */
if (need_pass_2)
@@ -1615,16 +1603,46 @@ emit_expr (exp, nbytes)
op = exp->X_op;
+ /* Handle a negative bignum. */
+ if (op == O_uminus
+ && exp->X_add_number == 0
+ && exp->X_add_symbol->sy_value.X_op == O_big
+ && exp->X_add_symbol->sy_value.X_add_number > 0)
+ {
+ int i;
+ unsigned long carry;
+
+ exp = &exp->X_add_symbol->sy_value;
+
+ /* Negate the bignum: one's complement each digit and add 1. */
+ carry = 1;
+ for (i = 0; i < exp->X_add_number; i++)
+ {
+ unsigned long next;
+
+ next = (((~ (generic_bignum[i] & LITTLENUM_MASK))
+ & LITTLENUM_MASK)
+ + carry);
+ generic_bignum[i] = next & LITTLENUM_MASK;
+ carry = next >> LITTLENUM_NUMBER_OF_BITS;
+ }
+
+ /* We can ignore any carry out, because it will be handled by
+ extra_digit if it is needed. */
+
+ extra_digit = (valueT) -1;
+ op = O_big;
+ }
+
if (op == O_absent || op == O_illegal)
{
as_warn ("zero assumed for missing expression");
exp->X_add_number = 0;
op = O_constant;
}
- else if (op == O_big)
+ else if (op == O_big && exp->X_add_number <= 0)
{
- as_bad ("%s number invalid; zero assumed",
- exp->X_add_number > 0 ? "bignum" : "floating point");
+ as_bad ("floating point number invalid; zero assumed");
exp->X_add_number = 0;
op = O_constant;
}
@@ -1658,6 +1676,28 @@ emit_expr (exp, nbytes)
}
#endif
+ /* If we have an integer, but the number of bytes is too large to
+ pass to md_number_to_chars, handle it as a bignum. */
+ if (op == O_constant && nbytes > sizeof (valueT))
+ {
+ valueT val;
+ int gencnt;
+
+ if (! exp->X_unsigned && exp->X_add_number < 0)
+ extra_digit = (valueT) -1;
+ val = (valueT) exp->X_add_number;
+ gencnt = 0;
+ do
+ {
+ generic_bignum[gencnt] = val & LITTLENUM_MASK;
+ val >>= LITTLENUM_NUMBER_OF_BITS;
+ ++gencnt;
+ }
+ while (val != 0);
+ op = exp->X_op = O_big;
+ exp->X_add_number = gencnt;
+ }
+
if (op == O_constant)
{
register long get;
@@ -1688,6 +1728,58 @@ emit_expr (exp, nbytes)
/* put bytes in right order. */
md_number_to_chars (p, (valueT) use, (int) nbytes);
}
+ else if (op == O_big)
+ {
+ int size;
+ LITTLENUM_TYPE *nums;
+
+ know (nbytes % CHARS_PER_LITTLENUM == 0);
+
+ size = exp->X_add_number * CHARS_PER_LITTLENUM;
+ if (nbytes < size)
+ {
+ as_warn ("Bignum truncated to %d bytes", nbytes);
+ size = nbytes;
+ }
+
+ if (target_big_endian)
+ {
+ while (nbytes > size)
+ {
+ md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
+ nbytes -= CHARS_PER_LITTLENUM;
+ p += CHARS_PER_LITTLENUM;
+ }
+
+ nums = generic_bignum + size / CHARS_PER_LITTLENUM;
+ while (size > 0)
+ {
+ --nums;
+ md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
+ size -= CHARS_PER_LITTLENUM;
+ p += CHARS_PER_LITTLENUM;
+ }
+ }
+ else
+ {
+ nums = generic_bignum;
+ while (size > 0)
+ {
+ md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
+ ++nums;
+ size -= CHARS_PER_LITTLENUM;
+ p += CHARS_PER_LITTLENUM;
+ nbytes -= CHARS_PER_LITTLENUM;
+ }
+
+ while (nbytes > 0)
+ {
+ md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
+ nbytes -= CHARS_PER_LITTLENUM;
+ p += CHARS_PER_LITTLENUM;
+ }
+ }
+ }
else
{
md_number_to_chars (p, (valueT) 0, (int) nbytes);
@@ -1725,7 +1817,7 @@ emit_expr (exp, nbytes)
#define TC_CONS_RELOC 0
#endif
#endif
- fix_new_exp (frag_now, p - frag_now->fr_literal, nbytes, exp, 0,
+ fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
TC_CONS_RELOC);
#endif /* TC_CONS_FIX_NEW */
#endif /* BFD_ASSEMBLER */
@@ -1808,7 +1900,7 @@ parse_bitfield_cons (exp, nbytes)
if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
{
- as_warn ("field width %d too big to fit in %d bytes: truncated to %d bits",
+ as_warn ("field width %lu too big to fit in %d bytes: truncated to %d bits",
width, nbytes, (BITS_PER_CHAR * nbytes));
width = BITS_PER_CHAR * nbytes;
} /* too big */
@@ -1851,6 +1943,7 @@ parse_bitfield_cons (exp, nbytes)
exp->X_add_number = value;
exp->X_op = O_constant;
+ exp->X_unsigned = 1;
} /* if looks like a bitfield */
} /* parse_bitfield_cons() */
@@ -1953,164 +2046,6 @@ parse_repeat_cons (exp, nbytes)
#endif /* REPEAT_CONS_EXPRESSIONS */
/*
- * big_cons()
- *
- * CONStruct more frag(s) of .quads, or .octa etc.
- * Makes 0 or more new frags.
- * If need_pass_2 == 1, generate no frag.
- * This understands only bignums, not expressions. Cons() understands
- * expressions.
- *
- * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal).
- *
- * This creates objects with struct obstack_control objs, destroying
- * any context objs held about a partially completed object. Beware!
- *
- *
- * I think it sucks to have 2 different types of integers, with 2
- * routines to read them, store them etc.
- * It would be nicer to permit bignums in expressions and only
- * complain if the result overflowed. However, due to "efficiency"...
- */
-/* Worker to do .quad etc statements. Clobbers input_line_pointer, checks
- end-of-line. 8=.quad 16=.octa ... */
-
-void
-big_cons (nbytes)
- register int nbytes;
-{
- register char c; /* input_line_pointer->c. */
- register int radix;
- register long length; /* Number of chars in an object. */
- register int digit; /* Value of 1 digit. */
- register int carry; /* For multi-precision arithmetic. */
- register int work; /* For multi-precision arithmetic. */
- register char *p; /* For multi-precision arithmetic. */
-
- extern const char hex_value[]; /* In hex_value.c. */
-
- /*
- * The following awkward logic is to parse ZERO or more strings,
- * comma seperated. Recall an expression includes its leading &
- * trailing blanks. We fake a leading ',' if there is (supposed to
- * be) a 1st expression, and keep demanding 1 expression for each ','.
- */
- if (is_it_end_of_statement ())
- {
- c = 0; /* Skip loop. */
- }
- else
- {
- c = ','; /* Do loop. */
- --input_line_pointer;
- }
- while (c == ',')
- {
- ++input_line_pointer;
- SKIP_WHITESPACE ();
- c = *input_line_pointer;
- /* C contains 1st non-blank character of what we hope is a number. */
- if (c == '0')
- {
- c = *++input_line_pointer;
- if (c == 'x' || c == 'X')
- {
- c = *++input_line_pointer;
- radix = 16;
- }
- else
- {
- radix = 8;
- }
- }
- else
- {
- radix = 10;
- }
- /*
- * This feature (?) is here to stop people worrying about
- * mysterious zero constants: which is what they get when
- * they completely omit digits.
- */
- if (hex_value[(unsigned char) c] >= radix)
- {
- as_bad ("Missing digits. 0 assumed.");
- }
- bignum_high = bignum_low - 1; /* Start constant with 0 chars. */
- for (;
- (digit = hex_value[(unsigned char) c]) < radix;
- c = *++input_line_pointer)
- {
- /* Multiply existing number by radix, then add digit. */
- carry = digit;
- for (p = bignum_low; p <= bignum_high; p++)
- {
- work = (*p & MASK_CHAR) * radix + carry;
- *p = work & MASK_CHAR;
- carry = work >> BITS_PER_CHAR;
- }
- if (carry)
- {
- grow_bignum ();
- *bignum_high = carry & MASK_CHAR;
- know ((carry & ~MASK_CHAR) == 0);
- }
- }
- length = bignum_high - bignum_low + 1;
- if (length > nbytes)
- {
- as_warn ("Most significant bits truncated in integer constant.");
- }
- else
- {
- register long leading_zeroes;
-
- for (leading_zeroes = nbytes - length;
- leading_zeroes;
- leading_zeroes--)
- {
- grow_bignum ();
- *bignum_high = 0;
- }
- }
- if (!need_pass_2)
- {
- char *src = bignum_low;
- p = frag_more (nbytes);
- if (target_big_endian)
- {
- int i;
- for (i = nbytes - 1; i >= 0; i--)
- p[i] = *src++;
- }
- else
- memcpy (p, bignum_low, (unsigned int) nbytes);
- }
- /* C contains character after number. */
- SKIP_WHITESPACE ();
- c = *input_line_pointer;
- /* C contains 1st non-blank character after number. */
- }
- demand_empty_rest_of_line ();
-} /* big_cons() */
-
-/* Extend bignum by 1 char. */
-static void
-grow_bignum ()
-{
- register unsigned long length;
-
- bignum_high++;
- if (bignum_high >= bignum_limit)
- {
- length = bignum_limit - bignum_low;
- bignum_low = xrealloc (bignum_low, length + length);
- bignum_high = bignum_low + length;
- bignum_limit = bignum_low + length + length;
- }
-} /* grow_bignum(); */
-
-/*
* float_cons()
*
* CONStruct some more frag chars of .floats .ffloats etc.
@@ -2162,7 +2097,7 @@ float_cons (float_type)
err = md_atof (float_type, temp, &length);
know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
know (length > 0);
- if (err && *err)
+ if (err)
{
as_bad ("Bad floating literal: %s", err);
ignore_rest_of_line ();
@@ -2639,7 +2574,7 @@ s_ignore (arg)
return;
} /* s_ignore() */
-
+
/*
* Handle .stabX directives, which used to be open-coded.
* So much creeping featurism overloaded the semantics that we decided
@@ -2655,34 +2590,6 @@ s_ignore (arg)
* don't need and invent information they need that you didn't supply.
*/
-void
-change_to_section (name, len, exp)
- char *name;
- unsigned int len;
- unsigned int exp;
-{
-#ifndef BFD_ASSEMBLER
-#ifdef MANY_SEGMENTS
- unsigned int i;
- extern segment_info_type segment_info[];
-
- /* Find out if we've already got a section of this name etc */
- for (i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0]; i++)
- {
- if (strncmp (segment_info[i].scnhdr.s_name, name, len) == 0)
- {
- subseg_set (i, exp);
- return;
- }
- }
- /* No section, add one */
- strncpy (segment_info[i].scnhdr.s_name, name, 8);
- segment_info[i].scnhdr.s_flags = 0 /* STYP_NOLOAD */;
- subseg_set (i, exp);
-#endif
-#endif
-}
-
/*
* Build a string dictionary entry for a .stabX symbol.
* The symbol is added to the .<secname>str section.
@@ -2690,73 +2597,60 @@ change_to_section (name, len, exp)
#ifdef SEPARATE_STAB_SECTIONS
-static unsigned int
+unsigned int
get_stab_string_offset (string, secname)
- char *string, *secname;
+ const char *string;
+ const char *secname;
{
- segT save_seg;
- segT seg;
- subsegT save_subseg;
unsigned int length;
- unsigned int old_gdb_string_index;
- char *clengthP;
- int i;
- char c;
- /* @@FIXME -- there should be no static data here!
- This also has the effect of making all stab string tables large enough
- to contain all the contents written to any of them. This only matters
- with the Solaris native compiler for the moment, but it should be fixed
- anyways. */
- static unsigned int gdb_string_index = 0;
-
- old_gdb_string_index = 0;
+ unsigned int retval;
+
+ retval = 0;
length = strlen (string);
- clengthP = (char *) &length;
if (length > 0)
{ /* Ordinary case. */
+ segT save_seg;
+ subsegT save_subseg;
+ char *newsecname;
+ segT seg;
+ int aligned;
+ char *p;
+
save_seg = now_seg;
save_subseg = now_subseg;
- /* Create the stabstr sections, if they are not already created. */
- {
- char *newsecname = xmalloc (strlen (secname) + 4);
- strcpy (newsecname, secname);
- strcat (newsecname, "str");
+ /* Create the stab string section. */
+ newsecname = xmalloc ((unsigned long) (strlen (secname) + 4));
+ strcpy (newsecname, secname);
+ strcat (newsecname, "str");
+
+ seg = subseg_new (newsecname, 0);
+
+ retval = seg_info (seg)->stabu.stab_string_size;
+ if (retval > 0)
+ free (newsecname);
+ else
+ {
+ /* Make sure the first string is empty. */
+ p = frag_more (1);
+ *p = 0;
+ retval = seg_info (seg)->stabu.stab_string_size = 1;
#ifdef BFD_ASSEMBLER
- seg = bfd_get_section_by_name (stdoutput, newsecname);
- if (seg == 0)
- {
- seg = bfd_make_section_old_way (stdoutput, newsecname);
- bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_ALLOC);
- }
+ bfd_set_section_flags (stdoutput, seg, SEC_READONLY);
#else
- subseg_new (newsecname, 0);
+ free (newsecname);
#endif
-/* free (newsecname);*/
- }
- subseg_set (seg, save_subseg);
- old_gdb_string_index = gdb_string_index;
- i = 0;
- while ((c = *string++))
- {
- i++;
- gdb_string_index++;
- FRAG_APPEND_1_CHAR (c);
- }
- {
- FRAG_APPEND_1_CHAR ((char) 0);
- i++;
- gdb_string_index++;
- }
- while (i % 4 != 0)
- {
- FRAG_APPEND_1_CHAR ((char) 0);
- i++;
- gdb_string_index++;
}
+
+ p = frag_more (length + 1);
+ strcpy (p, string);
+
+ seg_info (seg)->stabu.stab_string_size += length + 1;
+
subseg_set (save_seg, save_subseg);
}
- return old_gdb_string_index;
+
+ return retval;
}
#endif /* SEPARATE_STAB_SECTIONS */
@@ -2769,227 +2663,187 @@ s_stab_generic (what, secname)
int what;
char *secname;
{
- extern int listing;
-
- symbolS *symbol;
- char *string;
- int saved_type = 0;
- int length;
- int goof = 0;
long longint;
- segT saved_seg = now_seg;
- segT seg;
- subsegT saved_subseg = now_subseg;
- subsegT subseg;
- valueT valu;
-#ifdef SEPARATE_STAB_SECTIONS
- int seg_is_new = 0;
-#endif
-
- valu = ((char *) obstack_next_free (&frags)) - frag_now->fr_literal;
-
-#ifdef SEPARATE_STAB_SECTIONS
-#ifdef BFD_ASSEMBLER
- seg = bfd_get_section_by_name (stdoutput, secname);
- if (seg == 0)
+ char *string;
+ int type;
+ int other;
+ int desc;
+
+ /* The general format is:
+ .stabs "STRING",TYPE,OTHER,DESC,VALUE
+ .stabn TYPE,OTHER,DESC,VALUE
+ .stabd TYPE,OTHER,DESC
+ At this point input_line_pointer points after the pseudo-op and
+ any trailing whitespace. The argument what is one of 's', 'n' or
+ 'd' indicating which type of .stab this is. */
+
+ if (what != 's')
+ string = "";
+ else
{
- seg = subseg_new (secname, 0);
- bfd_set_section_flags (stdoutput, seg,
- SEC_READONLY | SEC_ALLOC | SEC_RELOC);
- subseg_set (saved_seg, subseg);
- seg_is_new = 1;
- }
-#else
- subseg_new (secname, 0);
-#endif
-#endif /* SEPARATE_STAB_SECTIONS */
+ int length;
- /*
- * Enter with input_line_pointer pointing past .stabX and any following
- * whitespace.
- */
- if (what == 's')
- {
string = demand_copy_C_string (&length);
SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
input_line_pointer++;
else
{
- as_bad ("I need a comma after symbol's name");
- goof = 1;
+ as_warn (".stabs: Missing comma");
+ ignore_rest_of_line ();
+ return;
}
}
- else
- string = "";
- /*
- * Input_line_pointer->after ','. String->symbol name.
- */
- if (!goof)
+ if (get_absolute_expression_and_terminator (&longint) != ',')
{
-#ifdef MAKE_STAB_SYMBOL
- MAKE_STAB_SYMBOL(symbol, string, secname);
-#else
- symbol = symbol_new (string, undefined_section, 0, (struct frag *) 0);
-#endif
- /* Make sure that the rest of this is going to work. */
- if (symbol == NULL)
- as_fatal ("no stab symbol created");
-
- switch (what)
- {
- case 'd':
- S_SET_NAME (symbol, NULL); /* .stabd feature. */
-#ifdef STAB_SYMBOL_SET_VALUE
- STAB_SYMBOL_SET_VALUE (symbol, valu);
-#else
- S_SET_VALUE (symbol, valu);
-#endif
-#if STAB_SYMBOL_SET_SEGMENT
-#else
- S_SET_SEGMENT (symbol, now_seg);
-#endif
- symbol->sy_frag = frag_now;
- break;
-
- case 'n':
- symbol->sy_frag = &zero_address_frag;
- break;
-
- case 's':
- symbol->sy_frag = &zero_address_frag;
- break;
-
- default:
- BAD_CASE (what);
- break;
- }
-
- if (get_absolute_expression_and_terminator (&longint) == ',')
- {
- saved_type = longint;
- S_SET_TYPE (symbol, saved_type);
- }
- else
- {
- as_bad ("I want a comma after the n_type expression");
- goof = 1;
- input_line_pointer--; /* Backup over a non-',' char. */
- }
+ as_warn (".stab%c: Missing comma", what);
+ ignore_rest_of_line ();
+ return;
}
+ type = longint;
- if (!goof)
+ if (get_absolute_expression_and_terminator (&longint) != ',')
{
- if (get_absolute_expression_and_terminator (&longint) == ',')
- S_SET_OTHER (symbol, longint);
- else
- {
- as_bad ("I want a comma after the n_other expression");
- goof = 1;
- input_line_pointer--; /* Backup over a non-',' char. */
- }
+ as_warn (".stab%c: Missing comma", what);
+ ignore_rest_of_line ();
+ return;
}
+ other = longint;
- if (!goof)
+ desc = get_absolute_expression ();
+ if (what == 's' || what == 'n')
{
- S_SET_DESC (symbol, get_absolute_expression ());
- if (what == 's' || what == 'n')
+ if (*input_line_pointer != ',')
{
- if (*input_line_pointer != ',')
- {
- as_bad ("I want a comma after the n_desc expression");
- goof = 1;
- }
- else
- {
- input_line_pointer++;
- }
+ as_warn (".stab%c: Missing comma", what);
+ ignore_rest_of_line ();
+ return;
}
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
}
- /* Line is messed up - ignore it and get out of here. */
- if (goof)
- {
- ignore_rest_of_line ();
- subseg_set (saved_seg, saved_subseg);
- return;
- }
-
- subseg_set (seg, subseg);
-
-#if 0 /* needed for elf only? */
- if (seg_is_new)
- /* allocate and discard -- filled in later */
- (void) frag_more (12);
-#endif
+ /* We have not gathered the type, other, and desc information. For
+ .stabs or .stabn, input_line_pointer is now pointing at the
+ value. */
#ifdef SEPARATE_STAB_SECTIONS
+ /* Output the stab information in a separate section. This is used
+ at least for COFF and ELF. */
{
- char *toP;
-
- subseg_new (secname, 0);
- toP = frag_more (8);
- /* the string index portion of the stab */
- md_number_to_chars (toP, (valueT) S_GET_OFFSET_2(symbol), 4);
- md_number_to_chars (toP + 4, (valueT) S_GET_TYPE(symbol), 1);
- md_number_to_chars (toP + 5, (valueT) S_GET_OTHER(symbol), 1);
- md_number_to_chars (toP + 6, (valueT) S_GET_DESC(symbol), 2);
- }
+ segT saved_seg = now_seg;
+ subsegT saved_subseg = now_subseg;
+ fragS *saved_frag = frag_now;
+ valueT dot;
+ segT seg;
+ unsigned int stroff;
+ char *p;
+
+ dot = frag_now_fix ();
+
+ seg = subseg_new (secname, 0);
+
+ if (! seg_info (seg)->hadone)
+ {
+#ifdef BFD_ASSEMBLER
+ bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_RELOC);
+#endif
+#ifdef INIT_STAB_SECTION
+ INIT_STAB_SECTION (seg);
#endif
+ seg_info (seg)->hadone = 1;
+ }
-#ifdef SEPARATE_STAB_SECTIONS
- if (what == 's' || what == 'n')
- {
- cons (4);
- input_line_pointer--;
- }
- else
- {
- char *p = frag_more (4);
- md_number_to_chars (p, 0, 4);
- }
- subseg_set (saved_seg, subseg);
+ stroff = get_stab_string_offset (string, secname);
+
+ /* At least for now, stabs in a special stab section are always
+ output as 12 byte blocks of information. */
+ p = frag_more (8);
+ md_number_to_chars (p, (valueT) stroff, 4);
+ md_number_to_chars (p + 4, (valueT) type, 1);
+ md_number_to_chars (p + 5, (valueT) other, 1);
+ md_number_to_chars (p + 6, (valueT) desc, 2);
+
+ if (what == 's' || what == 'n')
+ {
+ /* Pick up the value from the input line. */
+ cons (4);
+ input_line_pointer--;
+ }
+ else
+ {
+ const char *fake;
+ symbolS *symbol;
+ expressionS exp;
+
+ /* Arrange for a value representing the current location. */
+#ifdef DOT_LABEL_PREFIX
+ fake = ".L0\001";
#else
- if (what == 's' || what == 'n')
- {
- pseudo_set (symbol);
- S_SET_TYPE (symbol, saved_type);
- }
+ fake = "L0\001";
#endif
+ symbol = symbol_new (fake, saved_seg, dot, saved_frag);
-#if 0 /* for elf only? */
- if (what == 's' && S_GET_TYPE (symbol) == N_SO)
- {
- fragS *fragp = seg_info (seg)->frchainP->frch_root;
- while (fragp
- && fragp->fr_address + fragp->fr_fix < 12)
- fragp = fragp->fr_next;
- assert (fragp != 0);
- assert (fragp->fr_type == rs_fill);
- assert (fragp->fr_address == 0 && fragp->fr_fix >= 12);
- md_number_to_chars (fragp->fr_literal, (valueT) symbol->sy_name_offset,
- 4);
- }
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = symbol;
+ exp.X_add_number = 0;
+
+ emit_expr (&exp, 4);
+ }
+
+#ifdef OBJ_PROCESS_STAB
+ OBJ_PROCESS_STAB (seg, string, stroff, type, other, desc);
#endif
-#ifndef NO_LISTING
- if (listing)
- switch (S_GET_TYPE (symbol))
+ subseg_set (saved_seg, saved_subseg);
+ }
+#else /* ! SEPARATE_STAB_SECTIONS */
+#ifdef OBJ_PROCESS_STAB
+ OBJ_PROCESS_STAB (what, string, type, other, desc);
+#else
+ /* Put the stab information in the symbol table. */
+ {
+ symbolS *symbol;
+
+ symbol = symbol_new (string, undefined_section, 0,
+ (struct frag *) NULL);
+ if (what == 's' || what == 'n')
+ {
+ /* Pick up the value from the input line. */
+ symbol->sy_frag = &zero_address_frag;
+ pseudo_set (symbol);
+ }
+ else
{
- case N_SLINE:
- listing_source_line ((unsigned int) S_GET_DESC (symbol));
- break;
- case N_SO:
- case N_SOL:
- listing_source_file (string);
- break;
+ /* .stabd sets the name to NULL. Why? */
+ S_SET_NAME (symbol, NULL);
+ symbol->sy_frag = frag_now;
+ S_SET_VALUE (symbol, (valueT) frag_now_fix ());
}
-#endif /* !NO_LISTING */
-#ifdef SEPARATE_STAB_SECTIONS
- subseg_set (saved_seg, saved_subseg);
-#endif
+ S_SET_TYPE (symbol, type);
+ S_SET_OTHER (symbol, other);
+ S_SET_DESC (symbol, desc);
+ }
+#endif /* ! OBJ_PROCESS_STAB */
+#endif /* ! SEPARATE_STAB_SECTIONS */
+
+#ifndef NO_LISTING
+ if (listing)
+ {
+ switch (type)
+ {
+ case N_SLINE:
+ listing_source_line ((unsigned int) desc);
+ break;
+ case N_SO:
+ case N_SOL:
+ listing_source_file (string);
+ break;
+ }
+ }
+#endif /* ! NO_LISTING */
demand_empty_rest_of_line ();
}