/* coff object file format
- Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009
- Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of GAS.
#define OBJ_HEADER "obj-coff.h"
#include "as.h"
-#include "obstack.h"
+#include "safe-ctype.h"
#include "subsegs.h"
#ifdef TE_PE
#include "coff/pe.h"
#endif
+#ifdef OBJ_XCOFF
+#include "coff/xcoff.h"
+#endif
+
#define streq(a,b) (strcmp ((a), (b)) == 0)
#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
{
stack *st;
- st = malloc (sizeof (* st));
- if (!st)
- return NULL;
- st->data = malloc (chunk_size);
+ st = XNEW (stack);
+ st->data = XNEWVEC (char, chunk_size);
if (!st->data)
{
free (st);
if (st->pointer + st->element_size >= st->size)
{
st->size += st->chunk_size;
- if ((st->data = xrealloc (st->data, st->size)) == NULL)
- return NULL;
+ st->data = XRESIZEVEC (char, st->data, st->size);
}
memcpy (st->data + st->pointer, element, st->element_size);
st->pointer += st->element_size;
char numbuff[20];
sec = subseg_new (".drectve", 0);
- oldflags = bfd_get_section_flags (stdoutput, sec);
+ oldflags = bfd_section_flags (sec);
if (oldflags == SEC_NO_FLAGS)
{
- if (!bfd_set_section_flags (stdoutput, sec,
- TC_COFF_SECTION_DEFAULT_ATTRIBUTES))
+ if (!bfd_set_section_flags (sec, TC_COFF_SECTION_DEFAULT_ATTRIBUTES))
as_warn (_("error setting flags for \"%s\": %s"),
- bfd_section_name (stdoutput, sec),
+ bfd_section_name (sec),
bfd_errmsg (bfd_get_error ()));
}
/* Emit a string. Note no NUL-termination. */
- pfxlen = strlen (" -aligncomm:") + strlen (S_GET_NAME (symbolP)) + 1;
+ pfxlen = strlen (" -aligncomm:") + 2 + strlen (S_GET_NAME (symbolP)) + 1;
numlen = snprintf (numbuff, sizeof (numbuff), "%d", (int) align);
frag = frag_more (pfxlen + numlen);
- (void) sprintf (frag, " -aligncomm:%s,", S_GET_NAME (symbolP));
+ (void) sprintf (frag, " -aligncomm:\"%s\",", S_GET_NAME (symbolP));
memcpy (frag + pfxlen, numbuff, numlen);
/* Restore original subseg. */
subseg_set (current_seg, current_subseg);
}
#endif /* TE_PE */
-#define GET_FILENAME_STRING(X) \
- ((char *) (&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1])
-
/* @@ Ick. */
static segT
fetch_coff_debug_section (void)
coff_obj_symbol_new_hook (symbolS *symbolP)
{
long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
- char * s = xmalloc (sz);
+ char * s = XNEWVEC (char, sz);
memset (s, 0, sz);
coffsymbol (symbol_get_bfdsym (symbolP))->native = (combined_entry_type *) s;
+ coffsymbol (symbol_get_bfdsym (symbolP))->native->is_sym = TRUE;
S_SET_DATA_TYPE (symbolP, T_NULL);
S_SET_STORAGE_CLASS (symbolP, 0);
void
coff_obj_symbol_clone_hook (symbolS *newsymP, symbolS *orgsymP)
{
- long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
- combined_entry_type * s = xmalloc (sz);
+ long elts = OBJ_COFF_MAX_AUXENTRIES + 1;
+ combined_entry_type * s = XNEWVEC (combined_entry_type, elts);
- memcpy (s, coffsymbol (symbol_get_bfdsym (orgsymP))->native, sz);
+ memcpy (s, coffsymbol (symbol_get_bfdsym (orgsymP))->native,
+ elts * sizeof (combined_entry_type));
coffsymbol (symbol_get_bfdsym (newsymP))->native = s;
SF_SET (newsymP, SF_GET (orgsymP));
static void
add_lineno (fragS * frag, addressT offset, int num)
{
- struct line_no * new_line = xmalloc (sizeof (* new_line));
+ struct line_no * new_line = XNEW (struct line_no);
if (!current_lineno_sym)
abort ();
that shouldn't be loaded into memory, which requires linker
changes... For now, until proven otherwise, use .rdata. */
sec = subseg_new (".rdata$zzz", 0);
- bfd_set_section_flags (stdoutput, sec,
+ bfd_set_section_flags (sec,
((SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA)
& bfd_applicable_section_flags (stdoutput)));
}
char name_end; /* Char after the end of name. */
char *symbol_name; /* Name of the debug symbol. */
char *symbol_name_copy; /* Temporary copy of the name. */
- unsigned int symbol_name_length;
if (def_symbol_in_progress != NULL)
{
SKIP_WHITESPACES ();
- symbol_name = input_line_pointer;
- name_end = get_symbol_end ();
- symbol_name_length = strlen (symbol_name);
- symbol_name_copy = xmalloc (symbol_name_length + 1);
- strcpy (symbol_name_copy, symbol_name);
+ name_end = get_symbol_name (&symbol_name);
+ symbol_name_copy = xstrdup (symbol_name);
#ifdef tc_canonicalize_symbol_name
symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
#endif
if (S_IS_STRING (def_symbol_in_progress))
SF_SET_STRING (def_symbol_in_progress);
- *input_line_pointer = name_end;
+ (void) restore_line_pointer (name_end);
demand_empty_rest_of_line ();
}
-unsigned int dim_index;
-
static void
obj_coff_endef (int ignore ATTRIBUTE_UNUSED)
{
symbolS *symbolP = NULL;
- dim_index = 0;
if (def_symbol_in_progress == NULL)
{
as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
|| S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
- || (streq (bfd_get_section_name (stdoutput,
- S_GET_SEGMENT (def_symbol_in_progress)),
+ || (streq (bfd_section_name (S_GET_SEGMENT (def_symbol_in_progress)),
"*DEBUG*")
&& !SF_GET_TAG (def_symbol_in_progress))
|| S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
static void
obj_coff_dim (int ignore ATTRIBUTE_UNUSED)
{
- int dim_index;
+ int d_index;
if (def_symbol_in_progress == NULL)
{
S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
- for (dim_index = 0; dim_index < DIMNUM; dim_index++)
+ for (d_index = 0; d_index < DIMNUM; d_index++)
{
SKIP_WHITESPACES ();
- SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index,
+ SA_SET_SYM_DIMEN (def_symbol_in_progress, d_index,
get_absolute_expression ());
switch (*input_line_pointer)
/* Fall through. */
case '\n':
case ';':
- dim_index = DIMNUM;
+ d_index = DIMNUM;
break;
}
}
{
if (def_symbol_in_progress == NULL)
{
- as_warn (_(".size pseudo-op used outside of .def/.endef ignored."));
+ as_warn (_(".size pseudo-op used outside of .def/.endef: ignored."));
demand_empty_rest_of_line ();
return;
}
{
if (def_symbol_in_progress == NULL)
{
- as_warn (_(".scl pseudo-op used outside of .def/.endef ignored."));
+ as_warn (_(".scl pseudo-op used outside of .def/.endef: ignored."));
demand_empty_rest_of_line ();
return;
}
if (def_symbol_in_progress == NULL)
{
- as_warn (_(".tag pseudo-op used outside of .def/.endef ignored."));
+ as_warn (_(".tag pseudo-op used outside of .def/.endef: ignored."));
demand_empty_rest_of_line ();
return;
}
S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
- symbol_name = input_line_pointer;
- name_end = get_symbol_end ();
+ name_end = get_symbol_name (&symbol_name);
#ifdef tc_canonicalize_symbol_name
symbol_name = tc_canonicalize_symbol_name (symbol_name);
as_warn (_("tag not found for .tag %s"), symbol_name);
SF_SET_TAGGED (def_symbol_in_progress);
- *input_line_pointer = name_end;
+ (void) restore_line_pointer (name_end);
demand_empty_rest_of_line ();
}
{
if (def_symbol_in_progress == NULL)
{
- as_warn (_(".type pseudo-op used outside of .def/.endef ignored."));
+ as_warn (_(".type pseudo-op used outside of .def/.endef: ignored."));
demand_empty_rest_of_line ();
return;
}
{
if (def_symbol_in_progress == NULL)
{
- as_warn (_(".val pseudo-op used outside of .def/.endef ignored."));
+ as_warn (_(".val pseudo-op used outside of .def/.endef: ignored."));
demand_empty_rest_of_line ();
return;
}
if (is_name_beginner (*input_line_pointer))
{
- char *symbol_name = input_line_pointer;
- char name_end = get_symbol_end ();
+ char *symbol_name;
+ char name_end = get_symbol_name (&symbol_name);
#ifdef tc_canonicalize_symbol_name
- symbol_name = tc_canonicalize_symbol_name (symbol_name);
+ symbol_name = tc_canonicalize_symbol_name (symbol_name);
#endif
if (streq (symbol_name, "."))
{
}
/* Otherwise, it is the name of a non debug symbol and its value
will be calculated later. */
- *input_line_pointer = name_end;
+ (void) restore_line_pointer (name_end);
}
else
{
static const char *
weak_name2altname (const char * name)
{
- char *alt_name;
-
- alt_name = xmalloc (sizeof (weak_altprefix) + strlen (name));
- strcpy (alt_name, weak_altprefix);
- return strcat (alt_name, name);
+ return concat (weak_altprefix, name, (char *) NULL);
}
/* Return the name of the weak symbol corresponding to an
static const char *
weak_altname2name (const char * name)
{
- char * weak_name;
- char * dot;
-
gas_assert (weak_is_altname (name));
-
- weak_name = xstrdup (name + 6);
- if ((dot = strchr (weak_name, '.')))
- *dot = 0;
- return weak_name;
+ return xstrdup (name + 6);
}
/* Make a weak symbol name unique by
static const char *
weak_uniquify (const char * name)
{
- char *ret;
const char * unique = "";
#ifdef TE_PE
#endif
gas_assert (weak_is_altname (name));
- if (strchr (name + sizeof (weak_altprefix), '.'))
- return name;
-
- ret = xmalloc (strlen (name) + strlen (unique) + 2);
- strcpy (ret, name);
- strcat (ret, ".");
- strcat (ret, unique);
- return ret;
+ return concat (name, ".", unique, (char *) NULL);
}
void
do
{
- name = input_line_pointer;
- c = get_symbol_end ();
+ c = get_symbol_name (&name);
if (*name == 0)
{
as_warn (_("badly formed .weak directive ignored"));
c = 0;
symbolP = symbol_find_or_make (name);
*input_line_pointer = c;
- SKIP_WHITESPACE ();
+ SKIP_WHITESPACE_AFTER_NAME ();
S_SET_WEAK (symbolP);
if (c == ',')
}
}
- if (coff_last_function == 0 && SF_GET_FUNCTION (symp))
+ if (coff_last_function == 0 && SF_GET_FUNCTION (symp)
+ && S_IS_DEFINED (symp))
{
union internal_auxent *auxp;
sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));
}
- if (S_GET_STORAGE_CLASS (symp) == C_EFCN)
+ if (S_GET_STORAGE_CLASS (symp) == C_EFCN
+ && S_IS_DEFINED (symp))
{
if (coff_last_function == 0)
as_fatal (_("C_EFCN symbol for %s out of scope"),
/* We need i entries for line numbers, plus 1 for the first
entry which BFD will override, plus 1 for the last zero
entry (a marker for BFD). */
- l = xmalloc ((i + 2) * sizeof (* l));
+ l = XNEWVEC (alent, (i + 2));
coffsymbol (symbol_get_bfdsym (symp))->lineno = l;
l[i + 1].line_number = 0;
l[i + 1].u.sym = NULL;
fixp = fixp->fx_next;
}
}
- if (bfd_get_section_size (sec) == 0
+ if (bfd_section_size (sec) == 0
&& nrelocs == 0
&& nlnno == 0
&& sec != text_section
'o' for over
'w' for data
'd' (apparently m88k for data)
+ 'e' for exclude
'x' for text
'r' for read-only data
's' for shared data (PE)
'y' for noread
+ '0' - '9' for power-of-two alignment (GNU extension).
But if the argument is not a quoted string, treat it as a
subsegment number.
/* Strip out the section name. */
char *section_name;
char c;
+ int alignment = -1;
char *name;
unsigned int exp;
flagword flags, oldflags;
return;
}
- section_name = input_line_pointer;
- c = get_symbol_end ();
-
- name = xmalloc (input_line_pointer - section_name + 1);
- strcpy (name, section_name);
-
+ c = get_symbol_name (§ion_name);
+ name = xmemdup0 (section_name, input_line_pointer - section_name);
*input_line_pointer = c;
-
- SKIP_WHITESPACE ();
+ SKIP_WHITESPACE_AFTER_NAME ();
exp = 0;
flags = SEC_NO_FLAGS;
attr != '"'
&& ! is_end_of_line[attr])
{
+ if (ISDIGIT (attr))
+ {
+ alignment = attr - '0';
+ continue;
+ }
switch (attr)
{
+ case 'e':
+ /* Exclude section from linking. */
+ flags |= SEC_EXCLUDE;
+ break;
+
case 'b':
/* Uninitialised data section. */
flags |= SEC_ALLOC;
sec = subseg_new (name, (subsegT) exp);
- oldflags = bfd_get_section_flags (stdoutput, sec);
+ if (alignment >= 0)
+ sec->alignment_power = alignment;
+
+ oldflags = bfd_section_flags (sec);
if (oldflags == SEC_NO_FLAGS)
{
/* Set section flags for a new section just created by subseg_new.
flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
#endif
- if (! bfd_set_section_flags (stdoutput, sec, flags))
+ if (!bfd_set_section_flags (sec, flags))
as_warn (_("error setting flags for \"%s\": %s"),
- bfd_section_name (stdoutput, sec),
+ bfd_section_name (sec),
bfd_errmsg (bfd_get_error ()));
}
else if (flags != SEC_NO_FLAGS)
segT strsec;
char *p;
fragS *fragp;
- bfd_vma size, n_entries, mask;
- bfd_vma align_power = (bfd_vma)sec->alignment_power + OCTETS_PER_BYTE_POWER;
+ bfd_vma n_entries;
/* The COFF back end in BFD requires that all section sizes be
rounded up to multiples of the corresponding section alignments,
supposedly because standard COFF has no other way of encoding alignment
for sections. If your COFF flavor has a different way of encoding
section alignment, then skip this step, as TICOFF does. */
- size = bfd_get_section_size (sec);
- mask = ((bfd_vma) 1 << align_power) - 1;
+ bfd_vma size = bfd_section_size (sec);
#if !defined(TICOFF)
+ bfd_vma align_power = (bfd_vma) sec->alignment_power + OCTETS_PER_BYTE_POWER;
+ bfd_vma mask = ((bfd_vma) 1 << align_power) - 1;
+
if (size & mask)
{
bfd_vma new_size;
fragS *last;
new_size = (size + mask) & ~mask;
- bfd_set_section_size (stdoutput, sec, new_size);
+ bfd_set_section_size (sec, new_size);
/* If the size had to be rounded up, add some padding in
the last non-empty frag. */
#endif
{
symbolS *secsym = section_symbol (sec);
+ unsigned char sclass = C_STAT;
- S_SET_STORAGE_CLASS (secsym, C_STAT);
+#ifdef OBJ_XCOFF
+ if (bfd_section_flags (sec) & SEC_DEBUGGING)
+ sclass = C_DWARF;
+#endif
+ S_SET_STORAGE_CLASS (secsym, sclass);
S_SET_NUMBER_AUXILIARY (secsym, 1);
SF_SET_STATICS (secsym);
SA_SET_SCN_SCNLEN (secsym, size);
strsec = sec;
sec = subseg_get (STAB_SECTION_NAME, 0);
/* size is already rounded up, since other section will be listed first */
- size = bfd_get_section_size (strsec);
+ size = bfd_section_size (strsec);
- n_entries = bfd_get_section_size (sec) / 12 - 1;
+ n_entries = bfd_section_size (sec) / 12 - 1;
/* Find first non-empty frag. It should be large enough. */
fragp = seg_info (sec)->frchainP->frch_root;
void
obj_coff_init_stab_section (segT seg)
{
- char *file;
+ const char *file;
char *p;
char *stabstr_name;
unsigned int stroff;
p = frag_more (12);
/* Zero it out. */
memset (p, 0, 12);
- as_where (&file, (unsigned int *) NULL);
- stabstr_name = xmalloc (strlen (seg->name) + 4);
- strcpy (stabstr_name, seg->name);
- strcat (stabstr_name, "str");
- stroff = get_stab_string_offset (file, stabstr_name);
+ file = as_where ((unsigned int *) NULL);
+ stabstr_name = concat (seg->name, "str", (char *) NULL);
+ stroff = get_stab_string_offset (file, stabstr_name, TRUE);
know (stroff == 1);
md_number_to_chars (p, stroff, 4);
}
#ifdef DEBUG
+const char * s_get_name (symbolS *);
+
const char *
s_get_name (symbolS *s)
{
return ((s == NULL) ? "(NULL)" : S_GET_NAME (s));
}
+void symbol_dump (void);
+
void
symbol_dump (void)
{
0, /* ecoff_set_ext */
coff_obj_read_begin_hook,
coff_obj_symbol_new_hook,
- coff_obj_symbol_clone_hook
+ coff_obj_symbol_clone_hook,
+ coff_adjust_symtab
};