/* read.c - read a source file -
- Copyright (C) 1986-2015 Free Software Foundation, Inc.
+ Copyright (C) 1986-2018 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
02110-1301, USA. */
/* If your chars aren't 8 bits, you will change this a bit (eg. to 0xFF).
- But then, GNU isn't spozed to run on your machine anyway.
+ But then, GNU isn't supposed to run on your machine anyway.
(RMS is so shortsighted sometimes.) */
#define MASK_CHAR ((int)(unsigned char) -1)
#endif
char *input_line_pointer; /*->next char of source file to parse. */
+bfd_boolean input_from_string = FALSE;
#if BITS_PER_CHAR != 8
/* The following table is indexed by[(char)] and will break if
/* Variables for handling include file directory table. */
/* Table of pointers to directories to search for .include's. */
-char **include_dirs;
+const char **include_dirs;
/* How many are in the table. */
int include_dir_count;
#endif
static void do_s_func (int end_p, const char *default_prefix);
-static void do_align (int, char *, int, int);
static void s_align (int, int);
static void s_altmacro (int);
static void s_bad_end (int);
{"noformat", s_ignore, 0},
{"nolist", listing_list, 0}, /* Turn listing off. */
{"nopage", listing_nopage, 0},
+ {"nops", s_nops, 0},
{"octa", cons, 16},
{"offset", s_struct, 0},
{"org", s_org, 0},
get_absolute_expr (expressionS *exp)
{
expression_and_evaluate (exp);
+
if (exp->X_op != O_constant)
{
if (exp->X_op != O_absent)
/* We do this every time rather than just in s_bundle_align_mode
so that we catch any affected section without needing hooks all
over for all paths that do section changes. It's cheap enough. */
- record_alignment (now_seg, bundle_align_p2 - OCTETS_PER_BYTE_POWER);
+ if (bundle_align_p2 > OCTETS_PER_BYTE_POWER)
+ record_alignment (now_seg, bundle_align_p2 - OCTETS_PER_BYTE_POWER);
}
/* Assemble one instruction. This takes care of the bundle features
/* Make sure this hasn't pushed the locked sequence
past the bundle size. */
unsigned int bundle_size = pending_bundle_size (bundle_lock_frag);
- if (bundle_size > (1U << bundle_align_p2))
- as_bad (_("\
-.bundle_lock sequence at %u bytes but .bundle_align_mode limit is %u bytes"),
+ if (bundle_size > 1U << bundle_align_p2)
+ as_bad (_ (".bundle_lock sequence at %u bytes, "
+ "but .bundle_align_mode limit is %u bytes"),
bundle_size, 1U << bundle_align_p2);
}
else if (bundle_align_p2 > 0)
{
unsigned int insn_size = pending_bundle_size (insn_start_frag);
- if (insn_size > (1U << bundle_align_p2))
- as_bad (_("\
-single instruction is %u bytes long but .bundle_align_mode limit is %u"),
- (unsigned int) insn_size, 1U << bundle_align_p2);
+ if (insn_size > 1U << bundle_align_p2)
+ as_bad (_("single instruction is %u bytes long, "
+ "but .bundle_align_mode limit is %u bytes"),
+ insn_size, 1U << bundle_align_p2);
finish_bundle (insn_start_frag, insn_size);
}
#endif /* HANDLE_BUNDLE */
+static bfd_boolean
+in_bss (void)
+{
+ flagword flags = bfd_get_section_flags (stdoutput, now_seg);
+
+ return (flags & SEC_ALLOC) && !(flags & (SEC_LOAD | SEC_HAS_CONTENTS));
+}
+
+/* Guts of .align directive:
+ N is the power of two to which to align. A value of zero is accepted but
+ ignored: the default alignment of the section will be at least this.
+ FILL may be NULL, or it may point to the bytes of the fill pattern.
+ LEN is the length of whatever FILL points to, if anything. If LEN is zero
+ but FILL is not NULL then LEN is treated as if it were one.
+ MAX is the maximum number of characters to skip when doing the alignment,
+ or 0 if there is no maximum. */
+
+void
+do_align (unsigned int n, char *fill, unsigned int len, unsigned int max)
+{
+ if (now_seg == absolute_section || in_bss ())
+ {
+ if (fill != NULL)
+ while (len-- > 0)
+ if (*fill++ != '\0')
+ {
+ if (now_seg == absolute_section)
+ as_warn (_("ignoring fill value in absolute section"));
+ else
+ as_warn (_("ignoring fill value in section `%s'"),
+ segment_name (now_seg));
+ break;
+ }
+ fill = NULL;
+ len = 0;
+ }
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+#ifdef md_do_align
+ md_do_align (n, fill, len, max, just_record_alignment);
+#endif
+
+ /* Only make a frag if we HAVE to... */
+ if ((n > OCTETS_PER_BYTE_POWER) && !need_pass_2)
+ {
+ if (fill == NULL)
+ {
+ if (subseg_text_p (now_seg))
+ frag_align_code (n, max);
+ else
+ frag_align (n, 0, max);
+ }
+ else if (len <= 1)
+ frag_align (n, *fill, max);
+ else
+ frag_align_pattern (n, fill, len, max);
+ }
+
+#ifdef md_do_align
+ just_record_alignment: ATTRIBUTE_UNUSED_LABEL
+#endif
+
+ if (n > OCTETS_PER_BYTE_POWER)
+ record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
+}
+
/* We read the file, putting things into a web that represents what we
have been reading. */
void
-read_a_source_file (char *name)
+read_a_source_file (const char *name)
{
char nul_char;
char next_char;
/* Copy it for safe keeping. Also give an indication of
how much macro nesting is involved at this point. */
len = s - input_line_pointer;
- copy = (char *) xmalloc (len + macro_nest + 2);
+ copy = XNEWVEC (char, len + macro_nest + 2);
memset (copy, '>', macro_nest);
copy[macro_nest] = ' ';
memcpy (copy + macro_nest + 1, input_line_pointer, len);
assemble_one (s); /* Assemble 1 instruction. */
+ /* PR 19630: The backend may have set ilp to NULL
+ if it encountered a catastrophic failure. */
+ if (input_line_pointer == NULL)
+ as_fatal (_("unable to continue with assembly."));
+
*input_line_pointer++ = nul_char;
/* We resume loop AFTER the end-of-line from
that goes with this #APP There is one. The specs
guarantee it... */
tmp_len = buffer_limit - s;
- tmp_buf = (char *) xmalloc (tmp_len + 1);
+ tmp_buf = XNEWVEC (char, tmp_len + 1);
memcpy (tmp_buf, s, tmp_len);
do
{
else
num = buffer_limit - buffer;
- tmp_buf = (char *) xrealloc (tmp_buf, tmp_len + num);
+ tmp_buf = XRESIZEVEC (char, tmp_buf, tmp_len + num);
memcpy (tmp_buf + tmp_len, buffer, num);
tmp_len += num;
}
scrub_string_end = ends;
new_length = ends - s;
- new_buf = (char *) xmalloc (new_length);
+ new_buf = XNEWVEC (char, new_length);
new_tmp = new_buf;
for (;;)
{
break;
}
- new_buf = (char *) xrealloc (new_buf, new_length + 100);
+ new_buf = XRESIZEVEC (char, new_buf, new_length + 100);
new_tmp = new_buf + new_length;
new_length += 100;
}
as_fatal (_(".abort detected. Abandoning ship."));
}
-/* Guts of .align directive. N is the power of two to which to align.
- FILL may be NULL, or it may point to the bytes of the fill pattern.
- LEN is the length of whatever FILL points to, if anything. MAX is
- the maximum number of characters to skip when doing the alignment,
- or 0 if there is no maximum. */
-
-static void
-do_align (int n, char *fill, int len, int max)
-{
- if (now_seg == absolute_section)
- {
- if (fill != NULL)
- while (len-- > 0)
- if (*fill++ != '\0')
- {
- as_warn (_("ignoring fill value in absolute section"));
- break;
- }
- fill = NULL;
- len = 0;
- }
-
-#ifdef md_flush_pending_output
- md_flush_pending_output ();
-#endif
-#ifdef md_do_align
- md_do_align (n, fill, len, max, just_record_alignment);
-#endif
-
- /* Only make a frag if we HAVE to... */
- if (n != 0 && !need_pass_2)
- {
- if (fill == NULL)
- {
- if (subseg_text_p (now_seg))
- frag_align_code (n, max);
- else
- frag_align (n, 0, max);
- }
- else if (len <= 1)
- frag_align (n, *fill, max);
- else
- frag_align_pattern (n, fill, len, max);
- }
-
-#ifdef md_do_align
- just_record_alignment: ATTRIBUTE_UNUSED_LABEL
-#endif
-
- record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
-}
-
/* Handle the .align pseudo-op. A positive ARG is a default alignment
(in bytes). A negative ARG is the negative of the length of the
fill pattern. BYTES_P is non-zero if the alignment value should be
#endif
static void
-s_align (int arg, int bytes_p)
+s_align (signed int arg, int bytes_p)
{
unsigned int align_limit = TC_ALIGN_LIMIT;
unsigned int align;
char *stop = NULL;
char stopc = 0;
offsetT fill = 0;
- int max;
+ unsigned int max;
int fill_p;
if (flag_mri)
}
else
{
- int fill_len;
+ unsigned int fill_len;
if (arg >= 0)
fill_len = 1;
else
fill_len = -arg;
+
if (fill_len <= 1)
{
- char fill_char;
+ char fill_char = 0;
fill_char = fill;
do_align (align, &fill_char, fill_len, max);
char ab[16];
if ((size_t) fill_len > sizeof ab)
- abort ();
+ {
+ as_warn (_("fill pattern too long, truncating to %u"),
+ (unsigned) sizeof ab);
+ fill_len = sizeof ab;
+ }
+
md_number_to_chars (ab, fill, fill_len);
do_align (align, ab, fill_len, max);
}
char * name_end;
unsigned int C;
- start = name = xmalloc (len + 1);
+ start = name = XNEWVEC (char, len + 1);
name_end = name + SYM_NAME_CHUNK_LEN;
sofar = name - start;
len += SYM_NAME_CHUNK_LEN;
- start = xrealloc (start, len + 1);
+ start = XRESIZEVEC (char, start, len + 1);
name_end = start + len;
name = start + sofar;
}
if (mbstowcs (NULL, name, len) == (size_t) -1)
as_warn (_("symbol name not recognised in the current locale"));
}
- else if (is_name_beginner (c) || c == '\001')
+ else if (is_name_beginner (c) || (input_from_string && c == FAKE_LABEL_CHAR))
{
ptrdiff_t len;
name = input_line_pointer - 1;
- /* We accept \001 in a name in case this is
+ /* We accept FAKE_LABEL_CHAR in a name in case this is
being called with a constructed string. */
while (is_part_of_name (c = *input_line_pointer++)
- || c == '\001')
+ || (input_from_string && c == FAKE_LABEL_CHAR))
;
len = (input_line_pointer - name) - 1;
- start = xmalloc (len + 1);
+ start = XNEWVEC (char, len + 1);
memcpy (start, name, len);
start[len] = 0;
if (line_label != NULL)
{
- alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
- + (input_line_pointer - name)
- + 1);
+ alc = XNEWVEC (char, strlen (S_GET_NAME (line_label))
+ + (input_line_pointer - name) + 1);
sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
name = alc;
}
self-contained message, one that can be passed like the
demand_copy_C_string return value, and with no assumption on the
location of the name of the directive within the message. */
- char *msg
+ const char *msg
= (err ? _(".error directive invoked in source file")
: _(".warning directive invoked in source file"));
md_cons_align (1);
#endif
- get_known_segmented_expression (&rep_exp);
+ expression (&rep_exp);
if (*input_line_pointer == ',')
{
input_line_pointer++;
if (size && !need_pass_2)
{
+ if (now_seg == absolute_section)
+ {
+ if (rep_exp.X_op != O_constant)
+ as_bad (_("non-constant fill count for absolute section"));
+ else if (fill && rep_exp.X_add_number != 0)
+ as_bad (_("attempt to fill absolute section with non-zero value"));
+ abs_section_offset += rep_exp.X_add_number * size;
+ }
+ else if (fill
+ && (rep_exp.X_op != O_constant || rep_exp.X_add_number != 0)
+ && in_bss ())
+ as_bad (_("attempt to fill section `%s' with non-zero value"),
+ segment_name (now_seg));
+
if (rep_exp.X_op == O_constant)
{
p = frag_var (rs_fill, (int) size, (int) size,
void
s_irp (int irpc)
{
- char *file, *eol;
+ char * eol;
+ const char * file;
unsigned int line;
sb s;
const char *err;
sb out;
- as_where (&file, &line);
+ file = as_where (&line);
eol = find_end_of_line (input_line_pointer, 0);
sb_build (&s, eol - input_line_pointer);
}
void
-bss_alloc (symbolS *symbolP, addressT size, int align)
+bss_alloc (symbolS *symbolP, addressT size, unsigned int align)
{
char *pfrag;
segT current_seg = now_seg;
#endif
subseg_set (bss_seg, 1);
- if (align)
+ if (align > OCTETS_PER_BYTE_POWER)
{
record_alignment (bss_seg, align);
frag_align (align, 0, 0);
void
s_macro (int ignore ATTRIBUTE_UNUSED)
{
- char *file, *eol;
+ char *eol;
+ const char * file;
unsigned int line;
sb s;
const char *err;
const char *name;
- as_where (&file, &line);
+ file = as_where (&line);
eol = find_end_of_line (input_line_pointer, 0);
sb_build (&s, eol - input_line_pointer);
symbolS *sym = exp->X_add_symbol;
offsetT off = exp->X_add_number * OCTETS_PER_BYTE;
+ if (fill && in_bss ())
+ as_warn (_("ignoring fill value in section `%s'"),
+ segment_name (now_seg));
+
if (exp->X_op != O_constant && exp->X_op != O_symbol)
{
/* Handle complex expressions. */
if (c == ',')
{
- int align;
+ unsigned int align;
++input_line_pointer;
align = get_absolute_expression ();
}
else if (strcasecmp (seccmd, "align") == 0)
{
- int align;
+ unsigned int align;
(void) restore_line_pointer (c);
align = get_absolute_expression ();
void
s_rept (int ignore ATTRIBUTE_UNUSED)
{
- int count;
+ size_t count;
- count = get_absolute_expression ();
+ count = (size_t) get_absolute_expression ();
do_repeat (count, "REPT", "ENDR");
}
different directives to be used as the start/end keys. */
void
-do_repeat (int count, const char *start, const char *end)
+do_repeat (size_t count, const char *start, const char *end)
{
sb one;
sb many;
+ if (((ssize_t) count) < 0)
+ {
+ as_bad (_("negative count for %s - ignored"), start);
+ count = 0;
+ }
+
sb_new (&one);
if (!buffer_and_nest (start, end, &one, get_non_macro_line_sb))
{
}
/* Like do_repeat except that any text matching EXPANDER in the
- block is replaced by the itteration count. */
+ block is replaced by the iteration count. */
void
-do_repeat_with_expander (int count,
+do_repeat_with_expander (size_t count,
const char * start,
const char * end,
const char * expander)
sb one;
sb many;
+ if (((ssize_t) count) < 0)
+ {
+ as_bad (_("negative count for %s - ignored"), start);
+ count = 0;
+ }
+
sb_new (&one);
if (!buffer_and_nest (start, end, &one, get_non_macro_line_sb))
{
sb_build (& processed, one.len);
sb_add_sb (& processed, & one);
sub = strstr (processed.ptr, expander);
- len = sprintf (sub, "%d", count);
+ len = sprintf (sub, "%lu", (unsigned long) count);
gas_assert (len < 8);
strcpy (sub + len, sub + 8);
processed.len -= (8 - len);
if (listing & LISTING_SYMBOLS)
{
extern struct list_info_struct *listing_tail;
- fragS *dummy_frag = (fragS *) xcalloc (1, sizeof (fragS));
+ fragS *dummy_frag = XCNEW (fragS);
dummy_frag->line = listing_tail;
dummy_frag->fr_symbol = symbolP;
symbol_set_frag (symbolP, dummy_frag);
&& !S_CAN_BE_REDEFINED (symbolP))
{
as_bad (_("symbol `%s' is already defined"), name);
- symbolP = symbol_clone (symbolP, 0);
+ ignore_rest_of_line ();
+ input_line_pointer--;
+ return;
}
/* If the symbol is volatile, copy the symbol and replace the
original with the copy, so that previous uses of the symbol will
val.X_add_number = 0;
}
- if (val.X_op != O_constant
- || val.X_add_number < - 0x80
- || val.X_add_number > 0xff
- || (mult != 0 && mult != 1 && val.X_add_number != 0))
+ if ((val.X_op != O_constant
+ || val.X_add_number < - 0x80
+ || val.X_add_number > 0xff
+ || (mult != 0 && mult != 1 && val.X_add_number != 0))
+ && (now_seg != absolute_section && !in_bss ()))
{
resolve_expression (&exp);
if (exp.X_op != O_constant)
{
offsetT i;
- if (mult == 0)
- mult = 1;
- bytes = mult * exp.X_add_number;
- for (i = 0; i < exp.X_add_number; i++)
- emit_expr (&val, mult);
+ /* PR 20901: Check for excessive values.
+ FIXME: 1<<10 is an arbitrary limit. Maybe use maxpagesize instead ? */
+ if (exp.X_add_number < 0 || exp.X_add_number > (1 << 10))
+ as_bad (_("size value for space directive too large: %lx"),
+ (long) exp.X_add_number);
+ else
+ {
+ if (mult == 0)
+ mult = 1;
+ bytes = mult * exp.X_add_number;
+
+ for (i = 0; i < exp.X_add_number; i++)
+ emit_expr (&val, mult);
+ }
}
}
else
/* If we are in the absolute section, just bump the offset. */
if (now_seg == absolute_section)
{
+ if (val.X_op != O_constant || val.X_add_number != 0)
+ as_warn (_("ignoring fill value in absolute section"));
abs_section_offset += repeat;
goto getout;
}
make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
}
- if (p)
+ if ((val.X_op != O_constant || val.X_add_number != 0) && in_bss ())
+ as_warn (_("ignoring fill value in section `%s'"),
+ segment_name (now_seg));
+ else if (p)
*p = val.X_add_number;
}
mri_comment_end (stop, stopc);
}
+void
+s_nops (int ignore ATTRIBUTE_UNUSED)
+{
+ expressionS exp;
+ expressionS val;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+#ifdef md_cons_align
+ md_cons_align (1);
+#endif
+
+ expression (&exp);
+
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ expression (&val);
+ }
+ else
+ {
+ val.X_op = O_constant;
+ val.X_add_number = 0;
+ }
+
+ if (val.X_op == O_constant)
+ {
+ if (val.X_add_number < 0)
+ {
+ as_warn (_("negative nop control byte, ignored"));
+ val.X_add_number = 0;
+ }
+
+ if (!need_pass_2)
+ {
+ /* Store the no-op instruction control byte in the first byte
+ of frag. */
+ char *p;
+ symbolS *sym = make_expr_symbol (&exp);
+ p = frag_var (rs_space_nop, 1, 1, (relax_substateT) 0,
+ sym, (offsetT) 0, (char *) 0);
+ *p = val.X_add_number;
+ }
+ }
+ else
+ as_bad (_("unsupported variable nop control in .nops directive"));
+
+ demand_empty_rest_of_line ();
+}
+
/* This is like s_space, but the value is a floating point number with
the given precision. This is for the MRI dcb.s pseudo-op and
friends. */
}
else
{
- char *err;
+ const char *err;
err = md_atof (float_type, temp, &flen);
know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
symbolS *s = exp.X_add_symbol;
if (S_IS_COMMON (s))
- as_bad (_("`%s' can't be equated to common symbol '%s'"),
+ as_bad (_("`%s' can't be equated to common symbol `%s'"),
S_GET_NAME (symbolP), S_GET_NAME (s));
S_SET_SEGMENT (symbolP, seg);
char *r_name;
int c;
struct reloc_list *reloc;
- struct _bfd_rel { char *name; bfd_reloc_code_real_type code; };
- static struct _bfd_rel bfd_relocs[] = {
+ struct _bfd_rel { const char * name; bfd_reloc_code_real_type code; };
+ static struct _bfd_rel bfd_relocs[] =
+ {
{ "NONE", BFD_RELOC_NONE },
- { "8", BFD_RELOC_8 },
+ { "8", BFD_RELOC_8 },
{ "16", BFD_RELOC_16 },
{ "32", BFD_RELOC_32 },
{ "64", BFD_RELOC_64 }
};
- reloc = (struct reloc_list *) xmalloc (sizeof (*reloc));
+ reloc = XNEW (struct reloc_list);
if (flag_mri)
stop = mri_comment_field (&stopc);
case O_constant:
exp.X_add_symbol = section_symbol (now_seg);
exp.X_op = O_symbol;
- /* Fall thru */
+ /* Fallthru */
case O_symbol:
if (exp.X_add_number == 0)
{
reloc->u.a.offset_sym = exp.X_add_symbol;
break;
}
- /* Fall thru */
+ /* Fallthru */
default:
reloc->u.a.offset_sym = make_expr_symbol (&exp);
break;
break;
}
- as_where (&reloc->file, &reloc->line);
+ reloc->file = as_where (&reloc->line);
reloc->next = reloc_list;
reloc_list = reloc;
op = exp->X_op;
- /* Allow `.word 0' in the absolute section. */
- if (now_seg == absolute_section)
- {
- if (op != O_constant || exp->X_add_number != 0)
- as_bad (_("attempt to store value in absolute section"));
- abs_section_offset += nbytes;
- return;
- }
-
/* Handle a negative bignum. */
if (op == O_uminus
&& exp->X_add_number == 0
op = O_constant;
}
+ /* Allow `.word 0' in the absolute section. */
+ if (now_seg == absolute_section)
+ {
+ if (op != O_constant || exp->X_add_number != 0)
+ as_bad (_("attempt to store value in absolute section"));
+ abs_section_offset += nbytes;
+ return;
+ }
+
+ /* Allow `.word 0' in BSS style sections. */
+ if ((op != O_constant || exp->X_add_number != 0) && in_bss ())
+ as_bad (_("attempt to store non-zero value in section `%s'"),
+ segment_name (now_seg));
+
p = frag_more ((int) nbytes);
if (reloc != TC_PARSE_CONS_RETURN_NONE)
{
struct broken_word *x;
- x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
+ x = XNEW (struct broken_word);
x->next_broken_word = broken_words;
broken_words = x;
x->seg = now_seg;
if ((get & mask) != 0
&& ((get & mask) != mask
|| (get & hibit) == 0))
- { /* Leading bits contain both 0s & 1s. */
+ {
+ /* Leading bits contain both 0s & 1s. */
#if defined (BFD64) && BFD_HOST_64BIT_LONG_LONG
#ifndef __MSVCRT__
as_warn (_("value 0x%llx truncated to 0x%llx"),
if (nbytes < size)
{
int i = nbytes / CHARS_PER_LITTLENUM;
+
if (i != 0)
{
LITTLENUM_TYPE sign = 0;
if ((generic_bignum[--i]
& (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) != 0)
sign = ~(LITTLENUM_TYPE) 0;
+
while (++i < exp->X_add_number)
if (generic_bignum[i] != sign)
break;
}
+ else if (nbytes == 1)
+ {
+ /* We have nbytes == 1 and CHARS_PER_LITTLENUM == 2 (probably).
+ Check that bits 8.. of generic_bignum[0] match bit 7
+ and that they match all of generic_bignum[1..exp->X_add_number]. */
+ LITTLENUM_TYPE sign = (generic_bignum[0] & (1 << 7)) ? -1 : 0;
+ LITTLENUM_TYPE himask = LITTLENUM_MASK & ~ 0xFF;
+
+ if ((generic_bignum[0] & himask) == (sign & himask))
+ {
+ while (++i < exp->X_add_number)
+ if (generic_bignum[i] != sign)
+ break;
+ }
+ }
+
if (i < exp->X_add_number)
- as_warn (_("bignum truncated to %d bytes"), nbytes);
+ as_warn (ngettext ("bignum truncated to %d byte",
+ "bignum truncated to %d bytes",
+ nbytes),
+ nbytes);
size = nbytes;
}
if (size > nbytes)
{
- as_bad (_("%s relocations do not fit in %u bytes\n"),
+ as_bad (ngettext ("%s relocations do not fit in %u byte",
+ "%s relocations do not fit in %u bytes",
+ nbytes),
reloc_howto->name, nbytes);
return;
}
BITFIELD_CONS_EXPRESSIONS. */
static void
-parse_bitfield_cons (exp, nbytes)
- expressionS *exp;
- unsigned int nbytes;
+parse_bitfield_cons (expressionS *exp, unsigned int nbytes)
{
unsigned int bits_available = BITS_PER_CHAR * nbytes;
char *hold = input_line_pointer;
if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
{
- as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"),
+ as_warn (ngettext ("field width %lu too big to fit in %d byte:"
+ " truncated to %d bits",
+ "field width %lu too big to fit in %d bytes:"
+ " truncated to %d bits",
+ nbytes),
width, nbytes, (BITS_PER_CHAR * nbytes));
width = BITS_PER_CHAR * nbytes;
} /* Too big. */
To use this for a target, define REPEAT_CONS_EXPRESSIONS. */
static void
-parse_repeat_cons (exp, nbytes)
- expressionS *exp;
- unsigned int nbytes;
+parse_repeat_cons (expressionS *exp, unsigned int nbytes)
{
expressionS count;
int i;
{
char *p;
int length; /* Number of chars in an object. */
- char *err; /* Error from scanning floating literal. */
+ const char *err; /* Error from scanning floating literal. */
char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
if (is_it_end_of_statement ())
return;
}
+ if (now_seg == absolute_section)
+ {
+ as_bad (_("attempt to store float in absolute section"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (in_bss ())
+ {
+ as_bad (_("attempt to store float in section `%s'"),
+ segment_name (now_seg));
+ ignore_rest_of_line ();
+ return;
+ }
+
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
demand_empty_rest_of_line ();
}
\f
-/* Return the size of a LEB128 value. */
+/* LEB128 Encoding.
-static inline int
+ Note - we are using the DWARF standard's definition of LEB128 encoding
+ where each 7-bit value is a stored in a byte, *not* an octet. This
+ means that on targets where a byte contains multiple octets there is
+ a *huge waste of space*. (This also means that we do not have to
+ have special versions of these functions for when OCTETS_PER_BYTE_POWER
+ is non-zero).
+
+ If the 7-bit values were to be packed into N-bit bytes (where N > 8)
+ we would then have to consider whether multiple, successive LEB128
+ values should be packed into the bytes without padding (bad idea) or
+ whether each LEB128 number is padded out to a whole number of bytes.
+ Plus you have to decide on the endianness of packing octets into a
+ byte. */
+
+/* Return the size of a LEB128 value in bytes. */
+
+static inline unsigned int
sizeof_sleb128 (offsetT value)
{
int size = 0;
return size;
}
-static inline int
+static inline unsigned int
sizeof_uleb128 (valueT value)
{
int size = 0;
return size;
}
-int
+unsigned int
sizeof_leb128 (valueT value, int sign)
{
if (sign)
return sizeof_uleb128 (value);
}
-/* Output a LEB128 value. */
+/* Output a LEB128 value. Returns the number of bytes used. */
-static inline int
+static inline unsigned int
output_sleb128 (char *p, offsetT value)
{
char *orig = p;
return p - orig;
}
-static inline int
+static inline unsigned int
output_uleb128 (char *p, valueT value)
{
char *orig = p;
do
{
unsigned byte = (value & 0x7f);
+
value >>= 7;
if (value != 0)
/* More bytes to follow. */
return p - orig;
}
-int
+unsigned int
output_leb128 (char *p, valueT value, int sign)
{
if (sign)
/* Do the same for bignums. We combine sizeof with output here in that
we don't output for NULL values of P. It isn't really as critical as
- for "normal" values that this be streamlined. */
+ for "normal" values that this be streamlined. Returns the number of
+ bytes used. */
-static inline int
-output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
+static inline unsigned int
+output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, unsigned int size)
{
char *orig = p;
valueT val = 0;
return p - orig;
}
-static inline int
-output_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
+static inline unsigned int
+output_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, unsigned int size)
{
char *orig = p;
valueT val = 0;
return p - orig;
}
-static int
-output_big_leb128 (char *p, LITTLENUM_TYPE *bignum, int size, int sign)
+static unsigned int
+output_big_leb128 (char *p, LITTLENUM_TYPE *bignum, unsigned int size, int sign)
{
if (sign)
return output_big_sleb128 (p, bignum, size);
op = O_big;
}
+ if (now_seg == absolute_section)
+ {
+ if (op != O_constant || exp->X_add_number != 0)
+ as_bad (_("attempt to store value in absolute section"));
+ abs_section_offset++;
+ return;
+ }
+
+ if ((op != O_constant || exp->X_add_number != 0) && in_bss ())
+ as_bad (_("attempt to store non-zero value in section `%s'"),
+ segment_name (now_seg));
+
/* Let check_eh_frame know that data is being emitted. nbytes == -1 is
a signal that this is leb128 data. It shouldn't optimize this away. */
nbytes = (unsigned int) -1;
/* If we've got a constant, emit the thing directly right now. */
valueT value = exp->X_add_number;
- int size;
+ unsigned int size;
char *p;
size = sizeof_leb128 (value, sign);
p = frag_more (size);
- output_leb128 (p, value, sign);
+ if (output_leb128 (p, value, sign) > size)
+ abort ();
}
else if (op == O_big)
{
/* O_big is a different sort of constant. */
-
- int size;
+ int nbr_digits = exp->X_add_number;
+ unsigned int size;
char *p;
- size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
+ /* If the leading littenum is 0xffff, prepend a 0 to avoid confusion with
+ a signed number. Unary operators like - or ~ always extend the
+ bignum to its largest size. */
+ if (exp->X_unsigned
+ && nbr_digits < SIZE_OF_LARGE_NUMBER
+ && generic_bignum[nbr_digits - 1] == LITTLENUM_MASK)
+ generic_bignum[nbr_digits++] = 0;
+
+ size = output_big_leb128 (NULL, generic_bignum, nbr_digits, sign);
p = frag_more (size);
- output_big_leb128 (p, generic_bignum, exp->X_add_number, sign);
+ if (output_big_leb128 (p, generic_bignum, nbr_digits, sign) > size)
+ abort ();
}
else
{
do
{
- expression (&exp);
+ deferred_expression (&exp);
emit_leb128_expr (&exp, sign);
}
while (*input_line_pointer++ == ',');
static void
stringer_append_char (int c, int bitsize)
{
+ if (c && in_bss ())
+ as_bad (_("attempt to store non-empty string in section `%s'"),
+ segment_name (now_seg));
+
if (!target_big_endian)
FRAG_APPEND_1_CHAR (c);
md_cons_align (1);
#endif
+ /* If we have been switched into the abs_section then we
+ will not have an obstack onto which we can hang strings. */
+ if (now_seg == absolute_section)
+ {
+ as_bad (_("strings must be placed into a section"));
+ ignore_rest_of_line ();
+ return;
+ }
+
/* The following awkward logic is to parse ZERO or more strings,
comma separated. Recall a string expression includes spaces
before the opening '\"' and spaces after the closing '\"'.
{
c = ','; /* Do loop. */
}
- /* If we have been switched into the abs_section then we
- will not have an obstack onto which we can hang strings. */
- if (now_seg == absolute_section)
- {
- as_bad (_("strings must be placed into a section"));
- c = 0;
- ignore_rest_of_line ();
- }
while (c == ',' || c == '<' || c == '"')
{
c = *input_line_pointer++ & CHAR_MASK;
switch (c)
{
+ case 0:
+ /* PR 20902: Do not advance past the end of the buffer. */
+ -- input_line_pointer;
+ c = NOT_A_CHAR;
+ break;
+
case '\"':
c = NOT_A_CHAR;
break;
bump_line_counters ();
break;
+ case 0:
+ /* Do not advance past the end of the buffer. */
+ -- input_line_pointer;
+ c = NOT_A_CHAR;
+ break;
+
default:
#ifdef ONLY_STANDARD_ESCAPES
{
int i;
- path = (char *) xmalloc ((unsigned long) len + include_dir_maxlen + 5);
+ path = XNEWVEC (char, (unsigned long) len + include_dir_maxlen + 5);
for (i = 0; i < include_dir_count; i++)
{
}
demand_empty_rest_of_line ();
- path = (char *) xmalloc ((unsigned long) i
- + include_dir_maxlen + 5 /* slop */ );
+ path = XNEWVEC (char, (unsigned long) i
+ + include_dir_maxlen + 5 /* slop */ );
for (i = 0; i < include_dir_count; i++)
{
if (include_dir_count == 0)
{
- include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs));
+ include_dirs = XNEWVEC (const char *, 2);
include_dirs[0] = "."; /* Current dir. */
include_dir_count = 2;
}
else
{
include_dir_count++;
- include_dirs =
- (char **) xrealloc (include_dirs,
- include_dir_count * sizeof (*include_dirs));
+ include_dirs = XRESIZEVEC (const char *, include_dirs,
+ include_dir_count);
}
include_dirs[include_dir_count - 1] = path; /* New one. */
size = pending_bundle_size (bundle_lock_frag);
- if (size > (1U << bundle_align_p2))
- as_bad (_(".bundle_lock sequence is %u bytes, but bundle size only %u"),
- size, 1 << bundle_align_p2);
+ if (size > 1U << bundle_align_p2)
+ as_bad (_(".bundle_lock sequence is %u bytes, "
+ "but bundle size is only %u bytes"),
+ size, 1u << bundle_align_p2);
else
finish_bundle (bundle_lock_frag, size);
{
return _find_end_of_line (s, mri_string, 0, 0);
}
+
+static char *saved_ilp = NULL;
+static char *saved_limit;
+
+/* Use BUF as a temporary input pointer for calling other functions in this
+ file. BUF must be a C string, so that its end can be found by strlen.
+ Also sets the buffer_limit variable (local to this file) so that buffer
+ overruns should not occur. Saves the current input line pointer so that
+ it can be restored by calling restore_ilp().
+
+ Does not support recursion.
+
+ FIXME: This function is currently only used by stabs.c but that
+ should be extended to other files in the gas source directory. */
+
+void
+temp_ilp (char *buf)
+{
+ gas_assert (saved_ilp == NULL);
+ gas_assert (buf != NULL);
+
+ saved_ilp = input_line_pointer;
+ saved_limit = buffer_limit;
+ /* Prevent the assert in restore_ilp from triggering if
+ the input_line_pointer has not yet been initialised. */
+ if (saved_ilp == NULL)
+ saved_limit = saved_ilp = (char *) "";
+
+ input_line_pointer = buf;
+ buffer_limit = buf + strlen (buf);
+ input_from_string = TRUE;
+}
+
+/* Restore a saved input line pointer. */
+
+void
+restore_ilp (void)
+{
+ gas_assert (saved_ilp != NULL);
+
+ input_line_pointer = saved_ilp;
+ buffer_limit = saved_limit;
+ input_from_string = FALSE;
+
+ saved_ilp = NULL;
+}