/* ELF object file format
- Copyright (C) 1992-2018 Free Software Foundation, Inc.
+ Copyright (C) 1992-2020 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#include "safe-ctype.h"
#include "subsegs.h"
#include "obstack.h"
-#include "struc-symbol.h"
#include "dwarf2dbg.h"
#ifndef ECOFF_DEBUGGING
#ifdef NEED_ECOFF_DEBUG
#include "ecoff.h"
+#include "bfd/ecoff-bfd.h"
#endif
#ifdef TC_ALPHA
#include "elf/ppc.h"
#endif
-#ifdef TC_I370
-#include "elf/i370.h"
-#endif
-
#ifdef TC_I386
#include "elf/x86-64.h"
#endif
{"subsection", obj_elf_subsection, 0},
/* These are GNU extensions to aid in garbage collecting C++ vtables. */
- {"vtable_inherit", (void (*) (int)) &obj_elf_vtable_inherit, 0},
- {"vtable_entry", (void (*) (int)) &obj_elf_vtable_entry, 0},
+ {"vtable_inherit", obj_elf_vtable_inherit, 0},
+ {"vtable_entry", obj_elf_vtable_entry, 0},
/* A GNU extension for object attributes. */
{"gnu_attribute", obj_elf_gnu_attribute, 0},
{"4byte", cons, 4},
{"8byte", cons, 8},
/* These are used for dwarf2. */
- { "file", (void (*) (int)) dwarf2_directive_file, 0 },
+ { "file", dwarf2_directive_file, 0 },
{ "loc", dwarf2_directive_loc, 0 },
{ "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
void
elf_file_symbol (const char *s, int appfile)
{
+ asymbol *bsym;
+
if (!appfile
|| symbol_rootP == NULL
- || symbol_rootP->bsym == NULL
- || (symbol_rootP->bsym->flags & BSF_FILE) == 0)
+ || (bsym = symbol_get_bfdsym (symbol_rootP)) == NULL
+ || (bsym->flags & BSF_FILE) == 0)
{
symbolS *sym;
size_t name_length;
symbol_get_bfdsym (sym)->flags |= BSF_FILE;
if (symbol_rootP != sym
- && (symbol_rootP->bsym == NULL
- || !(symbol_rootP->bsym->flags & BSF_FILE)))
+ && ((bsym = symbol_get_bfdsym (symbol_rootP)) == NULL
+ || (bsym->flags & BSF_FILE) == 0))
{
symbol_remove (sym, &symbol_rootP, &symbol_lastP);
symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
attr |= ssect->attr;
}
- if ((attr & (SHF_ALLOC | SHF_GNU_MBIND)) == SHF_GNU_MBIND)
- as_fatal (_("SHF_ALLOC isn't set for GNU_MBIND section: %s"), name);
-
/* Convert ELF type and flags to BFD flags. */
flags = (SEC_RELOC
| ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
if (type == SHT_NOBITS)
seg_info (sec)->bss = 1;
- bfd_set_section_flags (stdoutput, sec, flags);
+ bfd_set_section_flags (sec, flags);
if (flags & SEC_MERGE)
sec->entsize = entsize;
elf_group_name (sec) = group_name;
}
static bfd_vma
-obj_elf_parse_section_letters (char *str, size_t len, bfd_boolean *is_clone)
+obj_elf_parse_section_letters (char *str, size_t len,
+ bfd_boolean *is_clone, bfd_vma *gnu_attr)
{
bfd_vma attr = 0;
*is_clone = FALSE;
attr |= SHF_TLS;
break;
case 'd':
- attr |= SHF_GNU_MBIND;
+ *gnu_attr |= SHF_GNU_MBIND;
break;
case '?':
*is_clone = TRUE;
char *beg;
int type, dummy;
bfd_vma attr;
+ bfd_vma gnu_attr;
int entsize;
int linkonce;
subsegT new_subsection = -1;
unsigned int info = 0;
-#ifndef TC_I370
if (flag_mri)
{
char mri_type;
return;
}
-#endif /* ! defined (TC_I370) */
name = obj_elf_section_name ();
if (name == NULL)
return;
+
+ symbolS * sym;
+ if ((sym = symbol_find (name)) != NULL
+ && ! symbol_section_p (sym)
+ && S_IS_DEFINED (sym)
+ && ! S_IS_VOLATILE (sym)
+ && ! S_CAN_BE_REDEFINED (sym))
+ {
+ as_bad (_("section name '%s' already defined as another symbol"), name);
+ ignore_rest_of_line ();
+ return;
+ }
type = SHT_NULL;
attr = 0;
+ gnu_attr = 0;
group_name = NULL;
entsize = 0;
linkonce = 0;
ignore_rest_of_line ();
return;
}
- attr |= obj_elf_parse_section_letters (beg, strlen (beg), &is_clone);
+ attr |= obj_elf_parse_section_letters (beg, strlen (beg),
+ &is_clone, &gnu_attr);
SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
++input_line_pointer;
if (ISDIGIT (* input_line_pointer))
- {
- type = strtoul (input_line_pointer, & input_line_pointer, 0);
- }
+ type = strtoul (input_line_pointer, &input_line_pointer, 0);
else
{
c = get_symbol_name (& beg);
(void) restore_line_pointer (c);
- type = obj_elf_section_type (beg, input_line_pointer - beg, TRUE);
+ type = obj_elf_section_type (beg,
+ input_line_pointer - beg,
+ TRUE);
}
}
else
}
}
- if ((attr & SHF_GNU_MBIND) != 0 && *input_line_pointer == ',')
+ if ((gnu_attr & SHF_GNU_MBIND) != 0 && *input_line_pointer == ',')
{
++input_line_pointer;
SKIP_WHITESPACE ();
c = get_symbol_name (& beg);
(void) restore_line_pointer (c);
- attr |= obj_elf_section_word (beg, input_line_pointer - beg, & type);
+ attr |= obj_elf_section_word (beg, input_line_pointer - beg,
+ &type);
SKIP_WHITESPACE ();
}
obj_elf_change_section (name, type, info, attr, entsize, group_name,
linkonce, push);
+ if ((gnu_attr & SHF_GNU_MBIND) != 0)
+ {
+ struct elf_backend_data *bed;
+
+ if ((attr & SHF_ALLOC) == 0)
+ as_bad (_("SHF_ALLOC isn't set for GNU_MBIND section: %s"), name);
+
+ bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput);
+ if (bed->elf_osabi == ELFOSABI_NONE)
+ bed->elf_osabi = ELFOSABI_GNU;
+ else if (bed->elf_osabi != ELFOSABI_GNU
+ && bed->elf_osabi != ELFOSABI_FREEBSD)
+ as_bad (_("GNU_MBIND section is supported only by GNU "
+ "and FreeBSD targets"));
+ elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_mbind;
+ }
+ elf_section_flags (now_seg) |= gnu_attr;
+
if (push && new_subsection != -1)
subseg_set (now_seg, new_subsection);
}
syntax is ".vtable_inherit CHILDNAME, PARENTNAME". */
struct fix *
-obj_elf_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
+obj_elf_get_vtable_inherit (void)
{
char *cname, *pname;
symbolS *csym, *psym;
0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT);
}
+/* This is a version of obj_elf_get_vtable_inherit() that is
+ suitable for use in struct _pseudo_type tables. */
+
+void
+obj_elf_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
+{
+ (void) obj_elf_get_vtable_inherit ();
+}
+
/* This handles the .vtable_entry pseudo-op, which is used to indicate
to the linker that a vtable slot was used. The syntax is
".vtable_entry tablename, offset". */
struct fix *
-obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
+obj_elf_get_vtable_entry (void)
{
symbolS *sym;
offsetT offset;
BFD_RELOC_VTABLE_ENTRY);
}
+/* This is a version of obj_elf_get_vtable_entry() that is
+ suitable for use in struct _pseudo_type tables. */
+
+void
+obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
+{
+ (void) obj_elf_get_vtable_entry ();
+}
+
#define skip_whitespace(str) do { if (*(str) == ' ') ++(str); } while (0)
static inline int
/* Create the .note section. */
note_secp = subseg_new (".note", 0);
- bfd_set_section_flags (stdoutput,
- note_secp,
- SEC_HAS_CONTENTS | SEC_READONLY);
+ bfd_set_section_flags (note_secp, SEC_HAS_CONTENTS | SEC_READONLY);
record_alignment (note_secp, 2);
/* Process the version string. */
|| strcmp (type_name, "10") == 0
|| strcmp (type_name, "STT_GNU_IFUNC") == 0)
{
- const struct elf_backend_data *bed;
-
- bed = get_elf_backend_data (stdoutput);
- if (!(bed->elf_osabi == ELFOSABI_GNU
- || bed->elf_osabi == ELFOSABI_FREEBSD
- /* GNU is still using the default value 0. */
- || bed->elf_osabi == ELFOSABI_NONE))
- as_bad (_("symbol type \"%s\" is supported only by GNU and FreeBSD targets"),
- type_name);
+ struct elf_backend_data *bed;
+
+ bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput);
+ if (bed->elf_osabi == ELFOSABI_NONE)
+ bed->elf_osabi = ELFOSABI_GNU;
+ else if (bed->elf_osabi != ELFOSABI_GNU
+ && bed->elf_osabi != ELFOSABI_FREEBSD)
+ as_bad (_("symbol type \"%s\" is supported only by GNU "
+ "and FreeBSD targets"), type_name);
+ elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
type = BSF_FUNCTION | BSF_GNU_INDIRECT_FUNCTION;
}
else if (strcmp (type_name, "gnu_unique_object") == 0)
struct elf_backend_data *bed;
bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput);
- if (!(bed->elf_osabi == ELFOSABI_GNU
- /* GNU is still using the default value 0. */
- || bed->elf_osabi == ELFOSABI_NONE))
+ if (bed->elf_osabi == ELFOSABI_NONE)
+ bed->elf_osabi = ELFOSABI_GNU;
+ else if (bed->elf_osabi != ELFOSABI_GNU)
as_bad (_("symbol type \"%s\" is supported only by GNU targets"),
type_name);
+ elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_unique;
type = BSF_OBJECT | BSF_GNU_UNIQUE;
- /* PR 10549: Always set OSABI field to GNU for objects containing unique symbols. */
- bed->elf_osabi = ELFOSABI_GNU;
}
#ifdef md_elf_symbol_type
else if ((type = md_elf_symbol_type (type_name, sym, elfsym)) != -1)
if (*input_line_pointer == '"')
++input_line_pointer;
- elfsym->symbol.flags |= type;
+#ifdef md_elf_symbol_type_change
+ if (!md_elf_symbol_type_change (sym, elfsym, type))
+#endif
+ {
+ flagword mask = BSF_FUNCTION | BSF_OBJECT;
+
+ if (type != BSF_FUNCTION)
+ mask |= BSF_GNU_INDIRECT_FUNCTION;
+ if (type != BSF_OBJECT)
+ {
+ mask |= BSF_GNU_UNIQUE | BSF_THREAD_LOCAL;
+
+ if (S_IS_COMMON (sym))
+ {
+ as_bad (_("cannot change type of common symbol '%s'"),
+ S_GET_NAME (sym));
+ mask = type = 0;
+ }
+ }
+
+ /* Don't warn when changing to STT_NOTYPE. */
+ if (type)
+ {
+ flagword new = (elfsym->symbol.flags & ~mask) | type;
+
+ if (new != (elfsym->symbol.flags | type))
+ as_warn (_("symbol '%s' already has its type set"), S_GET_NAME (sym));
+ elfsym->symbol.flags = new;
+ }
+ else
+ elfsym->symbol.flags &= ~mask;
+ }
demand_empty_rest_of_line ();
}
{
char *p;
comment_section = subseg_new (".comment", 0);
- bfd_set_section_flags (stdoutput, comment_section,
- SEC_READONLY | SEC_HAS_CONTENTS
- | SEC_MERGE | SEC_STRINGS);
+ bfd_set_section_flags (comment_section, (SEC_READONLY | SEC_HAS_CONTENTS
+ | SEC_MERGE | SEC_STRINGS));
comment_section->entsize = 1;
#ifdef md_elf_section_change_hook
md_elf_section_change_hook ();
/* Force the section to align to a longword boundary. Without this,
UnixWare ar crashes. */
- bfd_set_section_alignment (stdoutput, seg, 2);
+ bfd_set_section_alignment (seg, 2);
/* Make space for this first symbol. */
p = frag_more (12);
memset (p, 0, 12);
file = as_where (NULL);
stabstr_name = concat (segment_name (seg), "str", (char *) NULL);
- stroff = get_stab_string_offset (file, stabstr_name);
+ stroff = get_stab_string_offset (file, stabstr_name, TRUE);
know (stroff == 1 || (stroff == 0 && file[0] == '\0'));
md_number_to_chars (p, stroff, 4);
seg_info (seg)->stabu.p = p;
name = concat (sec->name, "str", NULL);
strsec = bfd_get_section_by_name (abfd, name);
if (strsec)
- strsz = bfd_section_size (abfd, strsec);
+ strsz = bfd_section_size (strsec);
else
strsz = 0;
- nsyms = bfd_section_size (abfd, sec) / 12 - 1;
+ nsyms = bfd_section_size (sec) / 12 - 1;
p = seg_info (sec)->stabu.p;
gas_assert (p != 0);
as_bad (_("symbol `%s' can not be both weak and common"),
S_GET_NAME (symp));
}
-
-#ifdef TC_MIPS
- /* The Irix 5 and 6 assemblers set the type of any common symbol and
- any undefined non-function symbol to STT_OBJECT. We try to be
- compatible, since newer Irix 5 and 6 linkers care. However, we
- only set undefined symbols to be STT_OBJECT if we are on Irix,
- because that is the only time gcc will generate the necessary
- .global directives to mark functions. */
-
- if (S_IS_COMMON (symp))
- symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
-
- if (strstr (TARGET_OS, "irix") != NULL
- && ! S_IS_DEFINED (symp)
- && (symbol_get_bfdsym (symp)->flags & BSF_FUNCTION) == 0)
- symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
-#endif
}
struct group_list
sec_name = ".group";
s = subseg_force_new (sec_name, 0);
if (s == NULL
- || !bfd_set_section_flags (stdoutput, s, flags)
- || !bfd_set_section_alignment (stdoutput, s, 2))
+ || !bfd_set_section_flags (s, flags)
+ || !bfd_set_section_alignment (s, 2))
{
as_fatal (_("can't create group: %s"),
bfd_errmsg (bfd_get_error ()));
/* Make sure that the signature symbol for the group has the
name of the group. */
sy = symbol_find_exact (group_name);
- if (!sy
- || (sy != symbol_lastP
- && (sy->sy_next == NULL
- || sy->sy_next->sy_previous != sy)))
+ if (!sy || !symbol_on_chain (sy, symbol_rootP, symbol_lastP))
{
/* Create the symbol now. */
sy = symbol_new (group_name, now_seg, (valueT) 0, frag_now);
group = elf_sec_group (head);
subseg_set (group, 0);
- bfd_set_section_size (stdoutput, group, size);
+ bfd_set_section_size (group, size);
group->contents = (unsigned char *) frag_more (size);
frag_now->fr_fix = frag_now_fix_octets ();
frag_wane (frag_now);
to force the ELF backend to allocate a file position, and then
write out the data. FIXME: Is this really the best way to do
this? */
- bfd_set_section_size
- (stdoutput, sec, bfd_ecoff_debug_size (stdoutput, &debug, debug_swap));
+ bfd_set_section_size (sec, bfd_ecoff_debug_size (stdoutput, &debug,
+ debug_swap));
/* Pass BUF to bfd_set_section_contents because this will
eventually become a call to fwrite, and ISO C prohibits
#endif /* NEED_ECOFF_DEBUG */
}
-#ifdef SCO_ELF
-
-/* Heavily plagiarized from obj_elf_version. The idea is to emit the
- SCO specific identifier in the .notes section to satisfy the SCO
- linker.
-
- This looks more complicated than it really is. As opposed to the
- "obvious" solution, this should handle the cross dev cases
- correctly. (i.e, hosting on a 64 bit big endian processor, but
- generating SCO Elf code) Efficiency isn't a concern, as there
- should be exactly one of these sections per object module.
-
- SCO OpenServer 5 identifies it's ELF modules with a standard ELF
- .note section.
-
- int_32 namesz = 4 ; Name size
- int_32 descsz = 12 ; Descriptive information
- int_32 type = 1 ;
- char name[4] = "SCO" ; Originator name ALWAYS SCO + NULL
- int_32 version = (major ver # << 16) | version of tools ;
- int_32 source = (tool_id << 16 ) | 1 ;
- int_32 info = 0 ; These are set by the SCO tools, but we
- don't know enough about the source
- environment to set them. SCO ld currently
- ignores them, and recommends we set them
- to zero. */
-
-#define SCO_MAJOR_VERSION 0x1
-#define SCO_MINOR_VERSION 0x1
-
-void
-sco_id (void)
-{
-
- char *name;
- unsigned int c;
- char ch;
- char *p;
- asection *seg = now_seg;
- subsegT subseg = now_subseg;
- Elf_Internal_Note i_note;
- Elf_External_Note e_note;
- asection *note_secp = NULL;
- int i, len;
-
- /* create the .note section */
-
- note_secp = subseg_new (".note", 0);
- bfd_set_section_flags (stdoutput,
- note_secp,
- SEC_HAS_CONTENTS | SEC_READONLY);
-
- /* process the version string */
-
- i_note.namesz = 4;
- i_note.descsz = 12; /* 12 descriptive bytes */
- i_note.type = NT_VERSION; /* Contains a version string */
-
- p = frag_more (sizeof (i_note.namesz));
- md_number_to_chars (p, i_note.namesz, 4);
-
- p = frag_more (sizeof (i_note.descsz));
- md_number_to_chars (p, i_note.descsz, 4);
-
- p = frag_more (sizeof (i_note.type));
- md_number_to_chars (p, i_note.type, 4);
-
- p = frag_more (4);
- strcpy (p, "SCO");
-
- /* Note: this is the version number of the ELF we're representing */
- p = frag_more (4);
- md_number_to_chars (p, (SCO_MAJOR_VERSION << 16) | (SCO_MINOR_VERSION), 4);
-
- /* Here, we pick a magic number for ourselves (yes, I "registered"
- it with SCO. The bottom bit shows that we are compat with the
- SCO ABI. */
- p = frag_more (4);
- md_number_to_chars (p, 0x4c520000 | 0x0001, 4);
-
- /* If we knew (or cared) what the source language options were, we'd
- fill them in here. SCO has given us permission to ignore these
- and just set them to zero. */
- p = frag_more (4);
- md_number_to_chars (p, 0x0000, 4);
-
- frag_align (2, 0, 0);
-
- /* We probably can't restore the current segment, for there likely
- isn't one yet... */
- if (seg && subseg)
- subseg_set (seg, subseg);
-
-}
-
-#endif /* SCO_ELF */
-
static void
elf_generate_asm_lineno (void)
{