/* read.c - read a source file -
- Copyright (C) 1986-2022 Free Software Foundation, Inc.
+ Copyright (C) 1986-2023 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#include "obstack.h"
#include "ecoff.h"
#include "dw2gencfi.h"
+#include "codeview.h"
#include "wchar.h"
+#include "filenames.h"
#include <limits.h>
const char **include_dirs;
/* How many are in the table. */
-int include_dir_count;
+size_t include_dir_count;
/* Length of longest in table. */
-int include_dir_maxlen = 1;
+size_t include_dir_maxlen;
#ifndef WORKING_DOT_WORD
struct broken_word *broken_words;
may be needed. */
static int mri_pending_align;
+/* Record the current function so that we can issue an error message for
+ misplaced .func,.endfunc, and also so that .endfunc needs no
+ arguments. */
+static char *current_name;
+static char *current_label;
+
#ifndef NO_LISTING
#ifdef OBJ_ELF
+static int dwarf_file;
+static int dwarf_line;
+
/* This variable is set to be non-zero if the next string we see might
be the name of the source file in DWARF debugging information. See
the comment in emit_expr for the format we look for. */
if (flag_mri)
lex_type['?'] = 3;
+ stabs_begin ();
+
+#ifndef WORKING_DOT_WORD
+ broken_words = NULL;
+ new_broken_words = 0;
+#endif
+
+ abs_section_offset = 0;
+
+ line_label = NULL;
+ mri_common_symbol = NULL;
+ mri_pending_align = 0;
+
+ current_name = NULL;
+ current_label = NULL;
+
+#ifndef NO_LISTING
+#ifdef OBJ_ELF
+ dwarf_file = 0;
+ dwarf_line = -1;
+ dwarf_file_string = 0;
+#endif
+#endif
+
+#ifdef HANDLE_BUNDLE
+ bundle_align_p2 = 0;
+ bundle_lock_frag = NULL;
+ bundle_lock_frchain = NULL;
+ bundle_lock_depth = 0;
+#endif
}
void
read_end (void)
{
+ stabs_end ();
poend ();
_obstack_free (&cond_obstack, NULL);
}
return get_absolute_expr (&exp);
}
-static int pop_override_ok = 0;
+static int pop_override_ok;
static const char *pop_table_name;
void
/* Do the target-specific pseudo ops. */
pop_table_name = "md";
+ pop_override_ok = 0;
md_pop_insert ();
/* Now object specific. Skip any that were in the target table. */
/* Now CFI ones. */
pop_table_name = "cfi";
- pop_override_ok = 1;
cfi_pop_insert ();
}
#ifndef NO_LISTING
/* In order to avoid listing macro expansion lines with labels
multiple times, keep track of which line was last issued. */
- static char *last_eol;
+ char *last_eol = NULL;
- last_eol = NULL;
#endif
while (input_line_pointer < buffer_limit)
{
/* Find the end of the current expanded macro line. */
s = find_end_of_line (input_line_pointer, flag_m68k_mri);
- if (s != last_eol)
+ if (s != last_eol
+ && !startswith (input_line_pointer,
+ !flag_m68k_mri ? " .linefile "
+ : " linefile "))
{
char *copy;
size_t len;
s_altmacro (int on)
{
demand_empty_rest_of_line ();
- macro_set_alternate (on);
+ flag_macro_alternate = on;
}
/* Read a symbol name from input_line_pointer.
/* Since quoted symbol names can contain non-ASCII characters,
check the string and warn if it cannot be recognised by the
current character set. */
- if (mbstowcs (NULL, name, len) == (size_t) -1)
+ /* PR 29447: mbstowcs ignores the third (length) parameter when
+ the first (destination) parameter is NULL. For clarity sake
+ therefore we pass 0 rather than 'len' as the third parameter. */
+ if (mbstowcs (NULL, name, 0) == (size_t) -1)
as_warn (_("symbol name not recognised in the current locale"));
}
else if (is_name_beginner (c) || (input_from_string && c == FAKE_LABEL_CHAR))
if (file || flags)
{
- linenum--;
+ demand_empty_rest_of_line ();
+
+ /* read_a_source_file() will bump the line number only if the line
+ is terminated by '\n'. */
+ if (input_line_pointer[-1] == '\n')
+ linenum--;
+
new_logical_line_flags (file, linenum, flags);
#ifdef LISTING
if (listing)
listing_source_line (linenum);
#endif
+ return;
}
}
- if (file || flags)
- demand_empty_rest_of_line ();
- else
- ignore_rest_of_line ();
+ ignore_rest_of_line ();
}
/* Handle the .end pseudo-op. Actually, the real work is done in
as_warn (_("repeat < 0; .fill ignored"));
size = 0;
}
-
- if (size && !need_pass_2)
+ else if (size && !need_pass_2)
{
- if (now_seg == absolute_section)
+ if (now_seg == absolute_section && rep_exp.X_op != O_constant)
+ {
+ as_bad (_("non-constant fill count for absolute section"));
+ size = 0;
+ }
+ else if (now_seg == absolute_section && fill && rep_exp.X_add_number != 0)
{
- 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;
+ as_bad (_("attempt to fill absolute section with non-zero value"));
+ size = 0;
}
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));
+ {
+ as_bad (_("attempt to fill section `%s' with non-zero value"),
+ segment_name (now_seg));
+ size = 0;
+ }
+ }
+
+ if (size && !need_pass_2)
+ {
+ if (now_seg == absolute_section)
+ abs_section_offset += rep_exp.X_add_number * size;
if (rep_exp.X_op == O_constant)
{
s_macro (int ignore ATTRIBUTE_UNUSED)
{
char *eol;
- const char * file;
- unsigned int line;
sb s;
- const char *err;
- const char *name;
-
- file = as_where (&line);
+ macro_entry *macro;
eol = find_end_of_line (input_line_pointer, 0);
sb_build (&s, eol - input_line_pointer);
{
sb label;
size_t len;
+ const char *name;
name = S_GET_NAME (line_label);
len = strlen (name);
sb_build (&label, len);
sb_add_buffer (&label, name, len);
- err = define_macro (0, &s, &label, get_macro_line_sb, file, line, &name);
+ macro = define_macro (&s, &label, get_macro_line_sb);
sb_kill (&label);
}
else
- err = define_macro (0, &s, NULL, get_macro_line_sb, file, line, &name);
- if (err != NULL)
- as_bad_where (file, line, err, name);
- else
+ macro = define_macro (&s, NULL, get_macro_line_sb);
+ if (macro != NULL)
{
if (line_label != NULL)
{
}
if (((NO_PSEUDO_DOT || flag_m68k_mri)
- && str_hash_find (po_hash, name) != NULL)
+ && str_hash_find (po_hash, macro->name) != NULL)
|| (!flag_m68k_mri
- && *name == '.'
- && str_hash_find (po_hash, name + 1) != NULL))
- as_warn_where (file,
- line,
- _("attempt to redefine pseudo-op `%s' ignored"),
- name);
+ && macro->name[0] == '.'
+ && str_hash_find (po_hash, macro->name + 1) != NULL))
+ {
+ as_warn_where (macro->file, macro->line,
+ _("attempt to redefine pseudo-op `%s' ignored"),
+ macro->name);
+ str_hash_delete (macro_hash, macro->name);
+ }
}
sb_kill (&s);
#ifdef TC_M68K
flag_m68k_mri = 1;
#endif
- macro_mri_mode (1);
}
else
{
#ifdef TC_M68K
flag_m68k_mri = 0;
#endif
- macro_mri_mode (0);
}
/* Operator precedence changes in m68k MRI mode, so we need to
if (!buffer_and_nest (start, end, &one, get_non_macro_line_sb))
{
as_bad (_("%s without %s"), start, end);
+ sb_kill (&one);
return;
}
if (exp.X_op == O_constant)
{
- offsetT repeat;
+ addressT repeat = exp.X_add_number;
+ addressT total;
- repeat = exp.X_add_number;
- if (mult)
- repeat *= mult;
- bytes = repeat;
- if (repeat <= 0)
+ bytes = 0;
+ if ((offsetT) repeat < 0)
+ {
+ as_warn (_(".space repeat count is negative, ignored"));
+ goto getout;
+ }
+ if (repeat == 0)
{
if (!flag_mri)
as_warn (_(".space repeat count is zero, ignored"));
- else if (repeat < 0)
- as_warn (_(".space repeat count is negative, ignored"));
goto getout;
}
+ if ((unsigned int) mult <= 1)
+ total = repeat;
+ else if (gas_mul_overflow (repeat, mult, &total)
+ || (offsetT) total < 0)
+ {
+ as_warn (_(".space repeat count overflow, ignored"));
+ goto getout;
+ }
+ bytes = total;
/* 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;
+ abs_section_offset += total;
goto getout;
}
if (mri_common_symbol != NULL)
{
S_SET_VALUE (mri_common_symbol,
- S_GET_VALUE (mri_common_symbol) + repeat);
+ S_GET_VALUE (mri_common_symbol) + total);
goto getout;
}
if (!need_pass_2)
p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
- (offsetT) repeat, (char *) 0);
+ (offsetT) total, (char *) 0);
}
else
{
int c;
struct reloc_list *reloc;
struct _bfd_rel { const char * name; bfd_reloc_code_real_type code; };
- static struct _bfd_rel bfd_relocs[] =
+ static const struct _bfd_rel bfd_relocs[] =
{
{ "NONE", BFD_RELOC_NONE },
{ "8", BFD_RELOC_8 },
/* When gcc emits DWARF 1 debugging pseudo-ops, a line number will
appear as a four byte positive constant in the .line section,
followed by a 2 byte 0xffff. Look for that case here. */
- {
- static int dwarf_line = -1;
-
- if (strcmp (segment_name (now_seg), ".line") != 0)
- dwarf_line = -1;
- else if (dwarf_line >= 0
- && nbytes == 2
- && exp->X_op == O_constant
- && (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
- listing_source_line ((unsigned int) dwarf_line);
- else if (nbytes == 4
- && exp->X_op == O_constant
- && exp->X_add_number >= 0)
- dwarf_line = exp->X_add_number;
- else
- dwarf_line = -1;
- }
+ if (strcmp (segment_name (now_seg), ".line") != 0)
+ dwarf_line = -1;
+ else if (dwarf_line >= 0
+ && nbytes == 2
+ && exp->X_op == O_constant
+ && (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
+ listing_source_line ((unsigned int) dwarf_line);
+ else if (nbytes == 4
+ && exp->X_op == O_constant
+ && exp->X_add_number >= 0)
+ dwarf_line = exp->X_add_number;
+ else
+ dwarf_line = -1;
/* When gcc emits DWARF 1 debugging pseudo-ops, a file name will
appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte
AT_sibling (0x12) followed by a four byte address of the sibling
followed by a 2 byte AT_name (0x38) followed by the name of the
file. We look for that case here. */
- {
- static int dwarf_file = 0;
-
- if (strcmp (segment_name (now_seg), ".debug") != 0)
- dwarf_file = 0;
- else if (dwarf_file == 0
- && nbytes == 2
- && exp->X_op == O_constant
- && exp->X_add_number == 0x11)
- dwarf_file = 1;
- else if (dwarf_file == 1
- && nbytes == 2
- && exp->X_op == O_constant
- && exp->X_add_number == 0x12)
- dwarf_file = 2;
- else if (dwarf_file == 2
- && nbytes == 4)
- dwarf_file = 3;
- else if (dwarf_file == 3
- && nbytes == 2
- && exp->X_op == O_constant
- && exp->X_add_number == 0x38)
- dwarf_file = 4;
- else
- dwarf_file = 0;
-
- /* The variable dwarf_file_string tells stringer that the string
- may be the name of the source file. */
- if (dwarf_file == 4)
- dwarf_file_string = 1;
- else
- dwarf_file_string = 0;
- }
+ if (strcmp (segment_name (now_seg), ".debug") != 0)
+ dwarf_file = 0;
+ else if (dwarf_file == 0
+ && nbytes == 2
+ && exp->X_op == O_constant
+ && exp->X_add_number == 0x11)
+ dwarf_file = 1;
+ else if (dwarf_file == 1
+ && nbytes == 2
+ && exp->X_op == O_constant
+ && exp->X_add_number == 0x12)
+ dwarf_file = 2;
+ else if (dwarf_file == 2
+ && nbytes == 4)
+ dwarf_file = 3;
+ else if (dwarf_file == 3
+ && nbytes == 2
+ && exp->X_op == O_constant
+ && exp->X_add_number == 0x38)
+ dwarf_file = 4;
+ else
+ dwarf_file = 0;
+
+ /* The variable dwarf_file_string tells stringer that the string
+ may be the name of the source file. */
+ if (dwarf_file == 4)
+ dwarf_file_string = 1;
+ else
+ dwarf_file_string = 0;
#endif
#endif
use = get & unmask;
if ((get & mask) != 0 && (-get & mask) != 0)
{
- char get_buf[128];
- char use_buf[128];
-
- /* These buffers help to ease the translation of the warning message. */
- sprintf_vma (get_buf, get);
- sprintf_vma (use_buf, use);
/* Leading bits contain both 0s & 1s. */
- as_warn (_("value 0x%s truncated to 0x%s"), get_buf, use_buf);
+ as_warn (_("value 0x%" PRIx64 " truncated to 0x%" PRIx64),
+ (uint64_t) get, (uint64_t) use);
}
/* Put bytes in right order. */
md_number_to_chars (p, use, (int) nbytes);
}
}
+/* Open FILENAME, first trying the unadorned file name, then if that
+ fails and the file name is not an absolute path, attempt to open
+ the file in current -I include paths. PATH is a preallocated
+ buffer which will be set to the file opened, or FILENAME if no file
+ is found. */
+
+FILE *
+search_and_open (const char *filename, char *path)
+{
+ FILE *f = fopen (filename, FOPEN_RB);
+ if (f == NULL && !IS_ABSOLUTE_PATH (filename))
+ {
+ for (size_t i = 0; i < include_dir_count; i++)
+ {
+ sprintf (path, "%s/%s", include_dirs[i], filename);
+ f = fopen (path, FOPEN_RB);
+ if (f != NULL)
+ return f;
+ }
+ }
+ strcpy (path, filename);
+ return f;
+}
+
/* .incbin -- include a file verbatim at the current location. */
void
demand_empty_rest_of_line ();
- /* Try opening absolute path first, then try include dirs. */
- binfile = fopen (filename, FOPEN_RB);
- if (binfile == NULL)
- {
- int i;
+ path = XNEWVEC (char, len + include_dir_maxlen + 2);
+ binfile = search_and_open (filename, path);
- path = XNEWVEC (char, (unsigned long) len + include_dir_maxlen + 5);
-
- for (i = 0; i < include_dir_count; i++)
- {
- sprintf (path, "%s/%s", include_dirs[i], filename);
-
- binfile = fopen (path, FOPEN_RB);
- if (binfile != NULL)
- break;
- }
-
- if (binfile == NULL)
- as_bad (_("file not found: %s"), filename);
- }
+ if (binfile == NULL)
+ as_bad (_("file not found: %s"), filename);
else
- path = xstrdup (filename);
-
- if (binfile)
{
long file_len;
struct stat filestat;
}
demand_empty_rest_of_line ();
- path = notes_alloc ((size_t) i + include_dir_maxlen + 5);
- for (i = 0; i < include_dir_count; i++)
- {
- strcpy (path, include_dirs[i]);
- strcat (path, "/");
- strcat (path, filename);
- if (0 != (try_file = fopen (path, FOPEN_RT)))
- {
- fclose (try_file);
- goto gotit;
- }
- }
+ path = notes_alloc (i + include_dir_maxlen + 2);
+ try_file = search_and_open (filename, path);
+ if (try_file)
+ fclose (try_file);
- notes_free (path);
- path = filename;
- gotit:
register_dependency (path);
input_scrub_insert_file (path);
}
void
-add_include_dir (char *path)
+init_include_dir (void)
{
- int i;
-
- if (include_dir_count == 0)
- {
- include_dirs = XNEWVEC (const char *, 2);
- include_dirs[0] = "."; /* Current dir. */
- include_dir_count = 2;
- }
- else
- {
- include_dir_count++;
- include_dirs = XRESIZEVEC (const char *, include_dirs,
- include_dir_count);
- }
+ include_dirs = XNEWVEC (const char *, 1);
+ include_dirs[0] = "."; /* Current dir. */
+ include_dir_count = 1;
+ include_dir_maxlen = 1;
+}
+void
+add_include_dir (char *path)
+{
+ include_dir_count++;
+ include_dirs = XRESIZEVEC (const char *, include_dirs, include_dir_count);
include_dirs[include_dir_count - 1] = path; /* New one. */
- i = strlen (path);
+ size_t i = strlen (path);
if (i > include_dir_maxlen)
include_dir_maxlen = i;
}
support that is required (calling dwarf2_emit_insn), we
let dwarf2dbg.c call as_where on its own. */
break;
+ case DEBUG_CODEVIEW:
+ codeview_generate_asm_lineno ();
+ break;
}
}
static void
do_s_func (int end_p, const char *default_prefix)
{
- /* Record the current function so that we can issue an error message for
- misplaced .func,.endfunc, and also so that .endfunc needs no
- arguments. */
- static char *current_name;
- static char *current_label;
-
if (end_p)
{
if (current_name == NULL)
return _find_end_of_line (s, mri_string, 0, 0);
}
-static char *saved_ilp = NULL;
+static char *saved_ilp;
static char *saved_limit;
/* Use BUF as a temporary input pointer for calling other functions in this