/* as.c - GAS main program.
- Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
Understands command arguments.
Has a few routines that don't fit in other modules because they
are shared.
-
+
bugs
-
+
: initialisers
Since no-one else says they will support them in future: I
don't support them now. */
#define COMMON
+/* Disable code to set FAKE_LABEL_NAME in obj-multi.h, to avoid circular
+ reference. */
+#define INITIALIZING_EMULS
+
#include "as.h"
#include "subsegs.h"
#include "output-file.h"
#include "dwarf2dbg.h"
#include "dw2gencfi.h"
#include "bfdver.h"
+#include "write.h"
#ifdef HAVE_ITBL_CPU
#include "itbl-ops.h"
#define itbl_init()
#endif
-#ifdef HAVE_SBRK
-#ifdef NEED_DECLARATION_SBRK
-extern void *sbrk ();
-#endif
-#endif
-
#ifdef USING_CGEN
/* Perform any cgen specific initialisation for gas. */
extern void gas_cgen_begin (void);
/* Enable verbose mode. */
int verbose = 0;
+/* Which version of DWARF CIE to produce. This default value of -1
+ indicates that this value has not been set yet, a default value is
+ provided in dwarf2_init. A different value can also be supplied by the
+ command line flag --gdwarf-cie-version, or by a target in
+ MD_AFTER_PARSE_ARGS. */
+int flag_dwarf_cie_version = -1;
+
+/* The maximum level of DWARF DEBUG information we should manufacture.
+ This defaults to 3 unless overridden by a command line option. */
+unsigned int dwarf_level = 3;
+
+#if defined OBJ_ELF || defined OBJ_MAYBE_ELF
+int flag_use_elf_stt_common = DEFAULT_GENERATE_ELF_STT_COMMON;
+bfd_boolean flag_generate_build_notes = DEFAULT_GENERATE_BUILD_NOTES;
+#endif
+
+/* Keep the output file. */
+static int keep_it = 0;
+
segT reg_section;
segT expr_section;
segT text_section;
#define EMULATION_ENVIRON "AS_EMULATION"
extern struct emulation mipsbelf, mipslelf, mipself;
-extern struct emulation mipsbecoff, mipslecoff, mipsecoff;
extern struct emulation i386coff, i386elf, i386aout;
extern struct emulation crisaout, criself;
select_emulation_mode (int argc, char **argv)
{
int i;
- char *p, *em = 0;
+ char *p;
+ const char *em = NULL;
for (i = 1; i < argc; i++)
if (!strncmp ("--em", argv[i], 4))
if (this_emulation->fake_label_name == 0)
{
if (this_emulation->leading_underscore)
- this_emulation->fake_label_name = "L0\001";
+ this_emulation->fake_label_name = FAKE_LABEL_NAME;
else
/* What other parameters should we test? */
- this_emulation->fake_label_name = ".L0\001";
+ this_emulation->fake_label_name = "." FAKE_LABEL_NAME;
}
}
#endif
VERSION, TARGET_ALIAS, BFD_VERSION_STRING);
}
+#ifdef DEFAULT_FLAG_COMPRESS_DEBUG
+enum compressed_debug_section_type flag_compress_debug
+ = COMPRESS_DEBUG_GABI_ZLIB;
+#endif
+
static void
show_usage (FILE * stream)
{
fprintf (stream, _("\
--alternate initially turn on alternate macro syntax\n"));
+#ifdef DEFAULT_FLAG_COMPRESS_DEBUG
+ fprintf (stream, _("\
+ --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi}]\n\
+ compress DWARF debug sections using zlib [default]\n"));
+ fprintf (stream, _("\
+ --nocompress-debug-sections\n\
+ don't compress DWARF debug sections\n"));
+#else
+ fprintf (stream, _("\
+ --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi}]\n\
+ compress DWARF debug sections using zlib\n"));
+ fprintf (stream, _("\
+ --nocompress-debug-sections\n\
+ don't compress DWARF debug sections [default]\n"));
+#endif
fprintf (stream, _("\
-D produce assembler debugging messages\n"));
fprintf (stream, _("\
- --debug-prefix-map OLD=NEW Map OLD to NEW in debug information\n"));
+ --debug-prefix-map OLD=NEW\n\
+ map OLD to NEW in debug information\n"));
fprintf (stream, _("\
--defsym SYM=VAL define symbol SYM to given value\n"));
#ifdef USE_EMULATIONS
{
int i;
- char *def_em;
+ const char *def_em;
fprintf (stream, "\
--em=[");
--execstack require executable stack for this object\n"));
fprintf (stream, _("\
--noexecstack don't require executable stack for this object\n"));
+ fprintf (stream, _("\
+ --size-check=[error|warning]\n\
+ ELF .size directive check (default --size-check=error)\n"));
+ fprintf (stream, _("\
+ --elf-stt-common=[no|yes] "));
+ if (DEFAULT_GENERATE_ELF_STT_COMMON)
+ fprintf (stream, _("(default: yes)\n"));
+ else
+ fprintf (stream, _("(default: no)\n"));
+ fprintf (stream, _("\
+ generate ELF common symbols with STT_COMMON type\n"));
+ fprintf (stream, _("\
+ --sectname-subst enable section name substitution sequences\n"));
+
+ fprintf (stream, _("\
+ --generate-missing-build-notes=[no|yes] "));
+#if DEFAULT_GENERATE_BUILD_NOTES
+ fprintf (stream, _("(default: yes)\n"));
+#else
+ fprintf (stream, _("(default: no)\n"));
#endif
+ fprintf (stream, _("\
+ generate GNU Build notes if none are present in the input\n"));
+#endif /* OBJ_ELF */
+
fprintf (stream, _("\
-f skip whitespace and comment preprocessing\n"));
fprintf (stream, _("\
fprintf (stream, _("\
--gstabs+ generate STABS debug info with GNU extensions\n"));
fprintf (stream, _("\
- --gdwarf-2 generate DWARF2 debugging information\n"));
+ --gdwarf-<N> generate DWARF<N> debugging information. 2 <= <N> <= 5\n"));
fprintf (stream, _("\
- --hash-size=<value> set the hash table size close to <value>\n"));
- fprintf (stream, _("\
- --help show this message and exit\n"));
+ --gdwarf-sections generate per-function section names for DWARF line information\n"));
fprintf (stream, _("\
--target-help show target specific options\n"));
fprintf (stream, _("\
fprintf (stream, _("\
-nocpp ignored\n"));
fprintf (stream, _("\
+ -no-pad-sections do not pad the end of sections to alignment boundaries\n"));
+ fprintf (stream, _("\
-o OBJFILE name the object-file output OBJFILE (default a.out)\n"));
fprintf (stream, _("\
-R fold data section into text section\n"));
fprintf (stream, _("\
- --reduce-memory-overheads \n\
- prefer smaller memory use at the cost of longer\n\
- assembly times\n"));
- fprintf (stream, _("\
--statistics print various measured statistics from execution\n"));
fprintf (stream, _("\
--strip-local-absolute strip local absolute symbols\n"));
--listing-cont-lines set the maximum number of continuation lines used\n\
for the output data column of the listing\n"));
fprintf (stream, _("\
- @FILE read options from FILE\n"));
+ @FILE read options from FILE\n"));
md_show_usage (stream);
OPTION_DEPFILE,
OPTION_GSTABS,
OPTION_GSTABS_PLUS,
- OPTION_GDWARF2,
+ OPTION_GDWARF_2,
+ OPTION_GDWARF_3,
+ OPTION_GDWARF_4,
+ OPTION_GDWARF_5,
+ OPTION_GDWARF_SECTIONS,
+ OPTION_GDWARF_CIE_VERSION,
OPTION_STRIP_LOCAL_ABSOLUTE,
OPTION_TRADITIONAL_FORMAT,
OPTION_WARN,
OPTION_TARGET_HELP,
OPTION_EXECSTACK,
OPTION_NOEXECSTACK,
+ OPTION_SIZE_CHECK,
+ OPTION_ELF_STT_COMMON,
+ OPTION_ELF_BUILD_NOTES,
+ OPTION_SECTNAME_SUBST,
OPTION_ALTERNATE,
OPTION_AL,
OPTION_HASH_TABLE_SIZE,
OPTION_REDUCE_MEMORY_OVERHEADS,
- OPTION_WARN_FATAL
+ OPTION_WARN_FATAL,
+ OPTION_COMPRESS_DEBUG,
+ OPTION_NOCOMPRESS_DEBUG,
+ OPTION_NO_PAD_SECTIONS /* = STD_BASE + 40 */
/* When you add options here, check that they do
not collide with OPTION_MD_BASE. See as.h. */
};
-
+
static const struct option std_longopts[] =
{
/* Note: commas are placed at the start of the line rather than
- the end of the preceeding line so that it is simpler to
+ the end of the preceding line so that it is simpler to
selectively add and remove lines from this list. */
{"alternate", no_argument, NULL, OPTION_ALTERNATE}
/* The entry for "a" is here to prevent getopt_long_only() from
,{"a", optional_argument, NULL, 'a'}
/* Handle -al=<FILE>. */
,{"al", optional_argument, NULL, OPTION_AL}
+ ,{"compress-debug-sections", optional_argument, NULL, OPTION_COMPRESS_DEBUG}
+ ,{"nocompress-debug-sections", no_argument, NULL, OPTION_NOCOMPRESS_DEBUG}
,{"debug-prefix-map", required_argument, NULL, OPTION_DEBUG_PREFIX_MAP}
,{"defsym", required_argument, NULL, OPTION_DEFSYM}
,{"dump-config", no_argument, NULL, OPTION_DUMPCONFIG}
#if defined OBJ_ELF || defined OBJ_MAYBE_ELF
,{"execstack", no_argument, NULL, OPTION_EXECSTACK}
,{"noexecstack", no_argument, NULL, OPTION_NOEXECSTACK}
+ ,{"size-check", required_argument, NULL, OPTION_SIZE_CHECK}
+ ,{"elf-stt-common", required_argument, NULL, OPTION_ELF_STT_COMMON}
+ ,{"sectname-subst", no_argument, NULL, OPTION_SECTNAME_SUBST}
+ ,{"generate-missing-build-notes", required_argument, NULL, OPTION_ELF_BUILD_NOTES}
#endif
,{"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL}
- ,{"gdwarf-2", no_argument, NULL, OPTION_GDWARF2}
- /* GCC uses --gdwarf-2 but GAS uses to use --gdwarf2,
+ ,{"gdwarf-2", no_argument, NULL, OPTION_GDWARF_2}
+ ,{"gdwarf-3", no_argument, NULL, OPTION_GDWARF_3}
+ ,{"gdwarf-4", no_argument, NULL, OPTION_GDWARF_4}
+ ,{"gdwarf-5", no_argument, NULL, OPTION_GDWARF_5}
+ /* GCC uses --gdwarf-2 but GAS used to to use --gdwarf2,
so we keep it here for backwards compatibility. */
- ,{"gdwarf2", no_argument, NULL, OPTION_GDWARF2}
+ ,{"gdwarf2", no_argument, NULL, OPTION_GDWARF_2}
+ ,{"gdwarf-sections", no_argument, NULL, OPTION_GDWARF_SECTIONS}
+ ,{"gdwarf-cie-version", required_argument, NULL, OPTION_GDWARF_CIE_VERSION}
,{"gen-debug", no_argument, NULL, 'g'}
,{"gstabs", no_argument, NULL, OPTION_GSTABS}
,{"gstabs+", no_argument, NULL, OPTION_GSTABS_PLUS}
,{"MD", required_argument, NULL, OPTION_DEPFILE}
,{"mri", no_argument, NULL, 'M'}
,{"nocpp", no_argument, NULL, OPTION_NOCPP}
+ ,{"no-pad-sections", no_argument, NULL, OPTION_NO_PAD_SECTIONS}
,{"no-warn", no_argument, NULL, 'W'}
,{"reduce-memory-overheads", no_argument, NULL, OPTION_REDUCE_MEMORY_OVERHEADS}
,{"statistics", no_argument, NULL, OPTION_STATISTICS}
dependent list. Include space for an extra NULL option and
always NULL terminate. */
shortopts = concat (std_shortopts, md_shortopts, (char *) NULL);
- longopts = xmalloc (sizeof (std_longopts) + md_longopts_size + sizeof (struct option));
+ longopts = (struct option *) xmalloc (sizeof (std_longopts)
+ + md_longopts_size + sizeof (struct option));
memcpy (longopts, std_longopts, sizeof (std_longopts));
memcpy (((char *) longopts) + sizeof (std_longopts), md_longopts, md_longopts_size);
memset (((char *) longopts) + sizeof (std_longopts) + md_longopts_size,
old_argv = *pargv;
/* Initialize a new argv that contains no options. */
- new_argv = xmalloc (sizeof (char *) * (old_argc + 1));
+ new_argv = XNEWVEC (char *, old_argc + 1);
new_argv[0] = old_argv[0];
new_argc = 1;
new_argv[new_argc] = NULL;
case 1: /* File name. */
if (!strcmp (optarg, "-"))
- optarg = "";
+ optarg = (char *) "";
new_argv[new_argc++] = optarg;
new_argv[new_argc] = NULL;
break;
case OPTION_NOCPP:
break;
+ case OPTION_NO_PAD_SECTIONS:
+ do_not_pad_sections_to_alignment = 1;
+ break;
+
case OPTION_STATISTICS:
flag_print_statistics = 1;
break;
case OPTION_VERSION:
/* This output is intended to follow the GNU standards document. */
printf (_("GNU assembler %s\n"), BFD_VERSION_STRING);
- printf (_("Copyright 2009 Free Software Foundation, Inc.\n"));
+ printf (_("Copyright (C) 2020 Free Software Foundation, Inc.\n"));
printf (_("\
This program is free software; you may redistribute it under the terms of\n\
the GNU General Public License version 3 or later.\n\
This program has absolutely no warranty.\n"));
+#ifdef TARGET_WITH_CPU
+ printf (_("This assembler was configured for a target of `%s' "
+ "and default,\ncpu type `%s'.\n"),
+ TARGET_ALIAS, TARGET_WITH_CPU);
+#else
printf (_("This assembler was configured for a target of `%s'.\n"),
TARGET_ALIAS);
+#endif
exit (EXIT_SUCCESS);
case OPTION_EMULATION:
#endif
exit (EXIT_SUCCESS);
+ case OPTION_COMPRESS_DEBUG:
+ if (optarg)
+ {
+#if defined OBJ_ELF || defined OBJ_MAYBE_ELF
+ if (strcasecmp (optarg, "none") == 0)
+ flag_compress_debug = COMPRESS_DEBUG_NONE;
+ else if (strcasecmp (optarg, "zlib") == 0)
+ flag_compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
+ else if (strcasecmp (optarg, "zlib-gnu") == 0)
+ flag_compress_debug = COMPRESS_DEBUG_GNU_ZLIB;
+ else if (strcasecmp (optarg, "zlib-gabi") == 0)
+ flag_compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
+ else
+ as_fatal (_("Invalid --compress-debug-sections option: `%s'"),
+ optarg);
+#else
+ as_fatal (_("--compress-debug-sections=%s is unsupported"),
+ optarg);
+#endif
+ }
+ else
+ flag_compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
+ break;
+
+ case OPTION_NOCOMPRESS_DEBUG:
+ flag_compress_debug = COMPRESS_DEBUG_NONE;
+ break;
+
case OPTION_DEBUG_PREFIX_MAP:
add_debug_prefix_map (optarg);
break;
as_fatal (_("bad defsym; format is --defsym name=value"));
*s++ = '\0';
i = bfd_scan_vma (s, (const char **) NULL, 0);
- n = xmalloc (sizeof *n);
+ n = XNEW (struct defsym_list);
n->next = defsyms;
n->name = optarg;
n->value = i;
break;
}
- n = xmalloc (sizeof * n);
+ n = XNEW (struct itbl_file_list);
n->next = itbl_files;
n->name = optarg;
itbl_files = n;
&& md_parse_option (optc, optarg))
continue;
+ /* We end up here for any -gsomething-not-already-a-long-option.
+ give some useful feedback on not (yet) supported -gdwarfxxx
+ versions/sections/options. */
+ if (strncmp (old_argv[optind - 1], "-gdwarf",
+ strlen ("-gdwarf")) == 0)
+ as_fatal (_("unknown DWARF option %s\n"), old_argv[optind - 1]);
+
if (md_debug_format_selector)
debug_type = md_debug_format_selector (& use_gnu_debug_info_extensions);
else if (IS_ELF)
- debug_type = DEBUG_DWARF2;
+ {
+ debug_type = DEBUG_DWARF2;
+ dwarf_level = 2;
+ }
else
debug_type = DEBUG_STABS;
break;
debug_type = DEBUG_STABS;
break;
- case OPTION_GDWARF2:
+ case OPTION_GDWARF_2:
+ debug_type = DEBUG_DWARF2;
+ dwarf_level = 2;
+ break;
+
+ case OPTION_GDWARF_3:
debug_type = DEBUG_DWARF2;
+ dwarf_level = 3;
+ break;
+
+ case OPTION_GDWARF_4:
+ debug_type = DEBUG_DWARF2;
+ dwarf_level = 4;
+ break;
+
+ case OPTION_GDWARF_5:
+ debug_type = DEBUG_DWARF2;
+ dwarf_level = 5;
+ break;
+
+ case OPTION_GDWARF_SECTIONS:
+ flag_dwarf_sections = TRUE;
+ break;
+
+ case OPTION_GDWARF_CIE_VERSION:
+ flag_dwarf_cie_version = atoi (optarg);
+ /* The available CIE versions are 1 (DWARF 2), 3 (DWARF 3), and 4
+ (DWARF 4 and 5). */
+ if (flag_dwarf_cie_version < 1
+ || flag_dwarf_cie_version == 2
+ || flag_dwarf_cie_version > 4)
+ as_fatal (_("Invalid --gdwarf-cie-version `%s'"), optarg);
+ switch (flag_dwarf_cie_version)
+ {
+ case 1:
+ if (dwarf_level < 2)
+ dwarf_level = 2;
+ break;
+ case 3:
+ if (dwarf_level < 3)
+ dwarf_level = 3;
+ break;
+ default:
+ if (dwarf_level < 4)
+ dwarf_level = 4;
+ break;
+ }
break;
case 'J':
flag_noexecstack = 1;
flag_execstack = 0;
break;
-#endif
+
+ case OPTION_SIZE_CHECK:
+ if (strcasecmp (optarg, "error") == 0)
+ flag_allow_nonconst_size = FALSE;
+ else if (strcasecmp (optarg, "warning") == 0)
+ flag_allow_nonconst_size = TRUE;
+ else
+ as_fatal (_("Invalid --size-check= option: `%s'"), optarg);
+ break;
+
+ case OPTION_ELF_STT_COMMON:
+ if (strcasecmp (optarg, "no") == 0)
+ flag_use_elf_stt_common = 0;
+ else if (strcasecmp (optarg, "yes") == 0)
+ flag_use_elf_stt_common = 1;
+ else
+ as_fatal (_("Invalid --elf-stt-common= option: `%s'"),
+ optarg);
+ break;
+
+ case OPTION_SECTNAME_SUBST:
+ flag_sectname_subst = 1;
+ break;
+
+ case OPTION_ELF_BUILD_NOTES:
+ if (strcasecmp (optarg, "no") == 0)
+ flag_generate_build_notes = FALSE;
+ else if (strcasecmp (optarg, "yes") == 0)
+ flag_generate_build_notes = TRUE;
+ else
+ as_fatal (_("Invalid --generate-missing-build-notes option: `%s'"),
+ optarg);
+ break;
+
+#endif /* OBJ_ELF */
+
case 'Z':
flag_always_generate_output = 1;
break;
break;
case OPTION_REDUCE_MEMORY_OVERHEADS:
- /* The only change we make at the moment is to reduce
- the size of the hash tables that we use. */
- set_gas_hash_table_size (4051);
break;
case OPTION_HASH_TABLE_SIZE:
- {
- unsigned long new_size;
-
- new_size = strtoul (optarg, NULL, 0);
- if (new_size)
- set_gas_hash_table_size (new_size);
- else
- as_fatal (_("--hash-size needs a numeric argument"));
- break;
- }
+ break;
}
}
static void
dump_statistics (void)
{
-#ifdef HAVE_SBRK
- char *lim = (char *) sbrk (0);
-#endif
long run_time = get_run_time () - start_time;
fprintf (stderr, _("%s: total time in assembly: %ld.%06ld\n"),
myname, run_time / 1000000, run_time % 1000000);
-#ifdef HAVE_SBRK
- fprintf (stderr, _("%s: data size %ld\n"),
- myname, (long) (lim - (char *) &environ));
-#endif
subsegs_print_statistics (stderr);
write_print_statistics (stderr);
close_output_file (void)
{
output_file_close (out_file_name);
+ if (!keep_it)
+ unlink_if_ordinary (out_file_name);
}
/* The interface between the macro code and gas expression handling. */
-static int
-macro_expr (const char *emsg, int idx, sb *in, int *val)
+static size_t
+macro_expr (const char *emsg, size_t idx, sb *in, offsetT *val)
{
- char *hold;
expressionS ex;
sb_terminate (in);
- hold = input_line_pointer;
- input_line_pointer = in->ptr + idx;
+ temp_ilp (in->ptr + idx);
expression_and_evaluate (&ex);
idx = input_line_pointer - in->ptr;
- input_line_pointer = hold;
+ restore_ilp ();
if (ex.X_op != O_constant)
as_bad ("%s", emsg);
- *val = (int) ex.X_add_number;
+ *val = ex.X_add_number;
return idx;
}
perform_an_assembly_pass (int argc, char ** argv)
{
int saw_a_file = 0;
+#ifndef OBJ_MACH_O
flagword applicable;
+#endif
need_pass_2 = 0;
+#ifndef OBJ_MACH_O
/* Create the standard sections, and those the assembler uses
internally. */
text_section = subseg_new (TEXT_SECTION_NAME, 0);
/* @@ FIXME -- we're setting the RELOC flag so that sections are assumed
to have relocs, otherwise we don't find out in time. */
applicable = bfd_applicable_section_flags (stdoutput);
- bfd_set_section_flags (stdoutput, text_section,
+ bfd_set_section_flags (text_section,
applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
| SEC_CODE | SEC_READONLY));
- bfd_set_section_flags (stdoutput, data_section,
+ bfd_set_section_flags (data_section,
applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
| SEC_DATA));
- bfd_set_section_flags (stdoutput, bss_section, applicable & SEC_ALLOC);
+ bfd_set_section_flags (bss_section, applicable & SEC_ALLOC);
seg_info (bss_section)->bss = 1;
+#endif
subseg_new (BFD_ABS_SECTION_NAME, 0);
subseg_new (BFD_UND_SECTION_NAME, 0);
reg_section = subseg_new ("*GAS `reg' section*", 0);
expr_section = subseg_new ("*GAS `expr' section*", 0);
+#ifndef OBJ_MACH_O
subseg_set (text_section, 0);
+#endif
/* This may add symbol table entries, which requires having an open BFD,
and sections already created. */
read_a_source_file ("");
}
\f
-#ifdef OBJ_ELF
-static void
-create_obj_attrs_section (void)
-{
- segT s;
- char *p;
- addressT addr;
- offsetT size;
- const char *name;
-
- size = bfd_elf_obj_attr_size (stdoutput);
- if (size)
- {
- name = get_elf_backend_data (stdoutput)->obj_attrs_section;
- if (!name)
- name = ".gnu.attributes";
- s = subseg_new (name, 0);
- elf_section_type (s)
- = get_elf_backend_data (stdoutput)->obj_attrs_section_type;
- bfd_set_section_flags (stdoutput, s, SEC_READONLY | SEC_DATA);
- addr = frag_now_fix ();
- p = frag_more (size);
- bfd_elf_set_obj_attr_contents (stdoutput, (bfd_byte *)p, size);
- }
-}
-#endif
-\f
int
main (int argc, char ** argv)
{
char ** argv_orig = argv;
+ struct stat sob;
int macro_strip_at;
- int keep_it;
start_time = get_run_time ();
+ signal_init ();
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
setlocale (LC_MESSAGES, "");
out_file_name = OBJ_DEFAULT_OUTPUT_FILE_NAME;
hex_init ();
- bfd_init ();
+ if (bfd_init () != BFD_INIT_MAGIC)
+ as_fatal (_("libbfd ABI mismatch"));
bfd_set_error_program_name (myname);
#ifdef USE_EMULATIONS
/* Call parse_args before any of the init/begin functions
so that switches like --hash-size can be honored. */
parse_args (&argc, &argv);
+
+ if (argc > 1 && stat (out_file_name, &sob) == 0)
+ {
+ int i;
+
+ for (i = 1; i < argc; ++i)
+ {
+ struct stat sib;
+
+ /* Check that the input file and output file are different. */
+ if (stat (argv[i], &sib) == 0
+ && sib.st_ino == sob.st_ino
+ /* POSIX emulating systems may support stat() but if the
+ underlying file system does not support a file serial number
+ of some kind then they will return 0 for the inode. So
+ two files with an inode of 0 may not actually be the same.
+ On real POSIX systems no ordinary file will ever have an
+ inode of 0. */
+ && sib.st_ino != 0
+ /* Different files may have the same inode number if they
+ reside on different devices, so check the st_dev field as
+ well. */
+ && sib.st_dev == sob.st_dev
+ /* PR 25572: Only check regular files. Devices, sockets and so
+ on might actually work as both input and output. Plus there
+ is a use case for using /dev/null as both input and output
+ when checking for command line option support in a script:
+ as --foo /dev/null -o /dev/null; if $? then ... */
+ && S_ISREG (sib.st_mode))
+ {
+ const char *saved_out_file_name = out_file_name;
+
+ /* Don't let as_fatal remove the output file! */
+ out_file_name = NULL;
+ as_fatal (_("The input '%s' and output '%s' files are the same"),
+ argv[i], saved_out_file_name);
+ }
+ }
+ }
+
symbol_begin ();
frag_init ();
subsegs_begin ();
output_file_create (out_file_name);
gas_assert (stdoutput != 0);
+ dot_symbol_init ();
+
#ifdef tc_init_after_args
tc_init_after_args ();
#endif
itbl_init ();
+ dwarf2_init ();
+
+ local_symbol_make (".gasversion.", absolute_section,
+ &predefined_address_frag, BFD_VERSION / 10000UL);
+
/* Now that we have fully initialized, and have created the output
file, define any symbols requested by --defsym command line
arguments. */
symbolS *sym;
struct defsym_list *next;
- sym = symbol_new (defsyms->name, absolute_section, defsyms->value,
- &zero_address_frag);
+ sym = symbol_new (defsyms->name, absolute_section,
+ &zero_address_frag, defsyms->value);
/* Make symbols defined on the command line volatile, so that they
can be redefined inside a source file. This makes this assembler's
behaviour compatible with earlier versions, but it may not be
md_end ();
#endif
-#ifdef OBJ_ELF
- if (IS_ELF)
- create_obj_attrs_section ();
-#endif
-
#if defined OBJ_ELF || defined OBJ_MAYBE_ELF
if ((flag_execstack || flag_noexecstack)
&& OUTPUT_FLAVOR == bfd_target_elf_flavour)
segT gnustack;
gnustack = subseg_new (".note.GNU-stack", 0);
- bfd_set_section_flags (stdoutput, gnustack,
+ bfd_set_section_flags (gnustack,
SEC_READONLY | (flag_execstack ? SEC_CODE : 0));
-
+
}
#endif
assembly debugging or on behalf of the compiler, emit it now. */
dwarf2_finish ();
- /* If we constructed dwarf2 .eh_frame info, either via .cfi
+ /* If we constructed dwarf2 .eh_frame info, either via .cfi
directives from the user or by the backend, emit it now. */
cfi_finish ();
- if (seen_at_least_1_file ()
- && (flag_always_generate_output || had_errors () == 0))
- keep_it = 1;
- else
- keep_it = 0;
+ keep_it = 0;
+ if (seen_at_least_1_file ())
+ {
+ int n_warns, n_errs;
+ char warn_msg[50];
+ char err_msg[50];
- /* This used to be done at the start of write_object_file in
- write.c, but that caused problems when doing listings when
- keep_it was zero. This could probably be moved above md_end, but
- I didn't want to risk the change. */
- subsegs_finish ();
+ write_object_file ();
- if (keep_it)
- write_object_file ();
+ n_warns = had_warnings ();
+ n_errs = had_errors ();
+
+ sprintf (warn_msg,
+ ngettext ("%d warning", "%d warnings", n_warns), n_warns);
+ sprintf (err_msg,
+ ngettext ("%d error", "%d errors", n_errs), n_errs);
+ if (flag_fatal_warnings && n_warns != 0)
+ {
+ if (n_errs == 0)
+ as_bad (_("%s, treating warnings as errors"), warn_msg);
+ n_errs += n_warns;
+ }
+
+ if (n_errs == 0)
+ keep_it = 1;
+ else if (flag_always_generate_output)
+ {
+ /* The -Z flag indicates that an object file should be generated,
+ regardless of warnings and errors. */
+ keep_it = 1;
+ fprintf (stderr, _("%s, %s, generating bad object file\n"),
+ err_msg, warn_msg);
+ }
+ }
fflush (stderr);
listing_print (listing_filename, argv_orig);
#endif
- if (flag_fatal_warnings && had_warnings () > 0 && had_errors () == 0)
- as_bad (_("%d warnings, treating warnings as errors"), had_warnings ());
-
- if (had_errors () > 0 && ! flag_always_generate_output)
- keep_it = 0;
-
- if (!keep_it)
- unlink_if_ordinary (out_file_name);
-
input_scrub_end ();
END_PROGRESS (myname);
/* Use xexit instead of return, because under VMS environments they
may not place the same interpretation on the value given. */
- if (had_errors () > 0)
+ if (had_errors () != 0)
xexit (EXIT_FAILURE);
/* Only generate dependency file if assembler was successful. */