/* ELF object file format
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002 Free Software Foundation, Inc.
+ 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#include "subsegs.h"
#include "obstack.h"
#include "struc-symbol.h"
+#include "dwarf2dbg.h"
#ifndef ECOFF_DEBUGGING
#define ECOFF_DEBUGGING 0
static symbolS *elf_common PARAMS ((int));
#ifdef NEED_ECOFF_DEBUG
-static boolean elf_get_extr PARAMS ((asymbol *, EXTR *));
+static bfd_boolean elf_get_extr PARAMS ((asymbol *, EXTR *));
static void elf_set_index PARAMS ((asymbol *, bfd_size_type));
#endif
{"2byte", cons, 2},
{"4byte", cons, 4},
{"8byte", cons, 8},
+ /* These are used for dwarf2. */
+ { "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
+ { "loc", dwarf2_directive_loc, 0 },
/* We need to trap the section changing calls to handle .previous. */
{"data", obj_elf_data, 0},
char *name;
char c;
char *p;
- int temp, size;
+ offsetT temp, size, sign;
symbolS *symbolP;
int have_align;
+ expressionS exp;
if (flag_mri && is_common)
{
return NULL;
}
input_line_pointer++; /* skip ',' */
- if ((temp = get_absolute_expression ()) < 0)
+ temp = get_absolute_expr (&exp);
+ sign = (offsetT) 1 << (stdoutput->arch_info->bits_per_address - 1);
+ size = temp & ((sign << 1) - 1);
+ if (temp != size || !exp.X_unsigned)
{
- as_bad (_(".COMMon length (%d.) <0! Ignored."), temp);
+ as_bad (_(".COMMon length (%ld) out of range, ignored."), (long) temp);
ignore_rest_of_line ();
return NULL;
}
- size = temp;
*p = 0;
symbolP = symbol_find_or_make (name);
*p = c;
{
if (S_GET_VALUE (symbolP) != (valueT) size)
{
- as_warn (_("length of .comm \"%s\" is already %ld; not changed to %d"),
- S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
+ as_warn (_("length of .comm \"%s\" is already %ld; not changed to %ld"),
+ S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP),
+ (long) size);
}
}
know (symbolP->sy_frag == &zero_address_frag);
temp = 0;
else
{
- temp = get_absolute_expression ();
- if (temp < 0)
+ temp = get_absolute_expr (&exp);
+ if (!exp.X_unsigned)
{
temp = 0;
as_warn (_("common alignment negative; 0 assumed"));
assert (elfsym);
- elfsym->internal_elf_sym.st_other = visibility;
+ elfsym->internal_elf_sym.st_other &= ~3;
+ elfsym->internal_elf_sym.st_other |= visibility;
if (c == ',')
{
other possibilities, but I don't know what they are. In any case,
BFD doesn't really let us set the section type. */
-/* Certain named sections have particular defined types, listed on p.
- 4-19 of the ABI. */
-struct special_section
-{
- const char *name;
- int type;
- int attributes;
-};
-
-static struct special_section const special_sections[] =
-{
- { ".bss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
- { ".comment", SHT_PROGBITS, 0 },
- { ".data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
- { ".data1", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
- { ".debug", SHT_PROGBITS, 0 },
- { ".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { ".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { ".line", SHT_PROGBITS, 0 },
- { ".note", SHT_NOTE, 0 },
- { ".rodata", SHT_PROGBITS, SHF_ALLOC },
- { ".rodata1", SHT_PROGBITS, SHF_ALLOC },
- { ".tbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
- { ".tdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
- { ".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
-#if 0
- /* FIXME: The current gcc, as of 2002-03-03, will emit
-
- .section .init_array,"aw",@progbits
-
- for __attribute__ ((section (".init_array"))). "@progbits" marks
- the incorrect section type. For now, we make them with
- SHT_PROGBITS. BFD will fix the section type. Gcc should be changed
- to emit
-
- .section .init_array
-
- */
- { ".init_array",SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
- { ".fini_array",SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
- { ".preinit_array",SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
-#else
- { ".init_array",SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
- { ".fini_array",SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
- { ".preinit_array",SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
-#endif
-
-#ifdef ELF_TC_SPECIAL_SECTIONS
- ELF_TC_SPECIAL_SECTIONS
-#endif
-
-#if 0
- /* The following section names are special, but they can not
- reasonably appear in assembler code. Some of the attributes are
- processor dependent. */
- { ".dynamic", SHT_DYNAMIC, SHF_ALLOC /* + SHF_WRITE */ },
- { ".dynstr", SHT_STRTAB, SHF_ALLOC },
- { ".dynsym", SHT_DYNSYM, SHF_ALLOC },
- { ".got", SHT_PROGBITS, 0 },
- { ".hash", SHT_HASH, SHF_ALLOC },
- { ".interp", SHT_PROGBITS, /* SHF_ALLOC */ },
- { ".plt", SHT_PROGBITS, 0 },
- { ".shstrtab",SHT_STRTAB, 0 },
- { ".strtab", SHT_STRTAB, /* SHF_ALLOC */ },
- { ".symtab", SHT_SYMTAB, /* SHF_ALLOC */ },
-#endif
-
- { NULL, 0, 0 }
-};
-
void
obj_elf_change_section (name, type, attr, entsize, group_name, linkonce, push)
const char *name;
asection *old_sec;
segT sec;
flagword flags;
- int i;
+ const struct bfd_elf_special_section *ssect;
#ifdef md_flush_pending_output
md_flush_pending_output ();
old_sec = bfd_get_section_by_name (stdoutput, name);
sec = subseg_new (name, 0);
+ ssect = _bfd_elf_get_sec_type_attr (stdoutput, name);
- /* See if this is one of the special sections. */
- for (i = 0; special_sections[i].name != NULL; i++)
- if (strcmp (name, special_sections[i].name) == 0)
- {
- if (type == SHT_NULL)
- type = special_sections[i].type;
- else if (type != special_sections[i].type)
- {
- if (old_sec == NULL)
- {
- as_warn (_("setting incorrect section type for %s"), name);
- }
- else
- {
- as_warn (_("ignoring incorrect section type for %s"), name);
- type = special_sections[i].type;
- }
- }
- if ((attr &~ special_sections[i].attributes) != 0
- && old_sec == NULL)
- {
- /* As a GNU extension, we permit a .note section to be
- allocatable. If the linker sees an allocateable .note
- section, it will create a PT_NOTE segment in the output
- file. */
- if (strcmp (name, ".note") != 0
- || attr != SHF_ALLOC)
+ if (ssect != NULL)
+ {
+ bfd_boolean override = FALSE;
+
+ if (type == SHT_NULL)
+ type = ssect->type;
+ else if (type != ssect->type)
+ {
+ if (old_sec == NULL
+ /* FIXME: gcc, as of 2002-10-22, will emit
+
+ .section .init_array,"aw",@progbits
+
+ for __attribute__ ((section (".init_array"))).
+ "@progbits" is incorrect. */
+ && ssect->type != SHT_INIT_ARRAY
+ && ssect->type != SHT_FINI_ARRAY
+ && ssect->type != SHT_PREINIT_ARRAY)
+ {
+ /* We allow to specify any type for a .note section. */
+ if (ssect->type != SHT_NOTE)
+ as_warn (_("setting incorrect section type for %s"),
+ name);
+ }
+ else
+ {
+ as_warn (_("ignoring incorrect section type for %s"),
+ name);
+ type = ssect->type;
+ }
+ }
+
+ if (old_sec == NULL && (attr & ~ssect->attr) != 0)
+ {
+ /* As a GNU extension, we permit a .note section to be
+ allocatable. If the linker sees an allocatable .note
+ section, it will create a PT_NOTE segment in the output
+ file. We also allow "x" for .note.GNU-stack. */
+ if (ssect->type == SHT_NOTE
+ && (attr == SHF_ALLOC || attr == SHF_EXECINSTR))
+ ;
+ /* Allow different SHF_MERGE and SHF_STRINGS if we have
+ something like .rodata.str. */
+ else if (ssect->suffix_length == -2
+ && name[ssect->prefix_length] == '.'
+ && (attr
+ & ~ssect->attr
+ & ~SHF_MERGE
+ & ~SHF_STRINGS) == 0)
+ ;
+ /* .interp, .strtab and .symtab can have SHF_ALLOC. */
+ else if (attr == SHF_ALLOC
+ && (strcmp (name, ".interp") == 0
+ || strcmp (name, ".strtab") == 0
+ || strcmp (name, ".symtab") == 0))
+ override = TRUE;
+ else
+ {
as_warn (_("setting incorrect section attributes for %s"),
name);
- }
- attr |= special_sections[i].attributes;
- break;
- }
+ override = TRUE;
+ }
+ }
+ if (!override && old_sec == NULL)
+ attr |= ssect->attr;
+ }
+
+ if (type != SHT_NULL)
+ elf_section_type (sec) = type;
+ if (attr != 0)
+ elf_section_flags (sec) = attr;
/* Convert ELF type and flags to BFD flags. */
flags = (SEC_RELOC
if (type == SHT_NOBITS)
seg_info (sec)->bss = 1;
+ if (linkonce)
+ flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
bfd_set_section_flags (stdoutput, sec, flags);
if (flags & SEC_MERGE)
sec->entsize = entsize;
elf_group_name (sec) = group_name;
- elf_linkonce_p (sec) = linkonce;
/* Add a symbol for this section to the symbol table. */
secsym = symbol_find (name);
if (((old_sec->flags ^ flags)
& (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
| SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS
- | SEC_THREAD_LOCAL))
- || linkonce != elf_linkonce_p (sec))
+ | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
+ | SEC_THREAD_LOCAL)))
as_warn (_("ignoring changed section attributes for %s"), name);
if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
as_warn (_("ignoring changed section entity size for %s"), name);
attr |= md_attr;
else
#endif
- {
- as_warn ("%s", bad_msg);
- attr = -1;
- }
+ as_fatal ("%s", bad_msg);
}
break;
}
return SHF_ALLOC;
if (len == 9 && strncmp (str, "execinstr", 9) == 0)
return SHF_EXECINSTR;
+ if (len == 3 && strncmp (str, "tls", 3) == 0)
+ return SHF_TLS;
#ifdef md_elf_section_word
{
return SHT_PROGBITS;
if (len == 6 && strncmp (str, "nobits", 6) == 0)
return SHT_NOBITS;
+ if (len == 4 && strncmp (str, "note", 4) == 0)
+ return SHT_NOTE;
#ifdef md_elf_section_type
{
name = xmalloc (end - input_line_pointer + 1);
memcpy (name, input_line_pointer, end - input_line_pointer);
name[end - input_line_pointer] = '\0';
+#ifdef tc_canonicalize_section_name
+ name = tc_canonicalize_section_name (name);
+#endif
input_line_pointer = end;
}
SKIP_WHITESPACE ();
}
++input_line_pointer;
+ SKIP_WHITESPACE ();
name = input_line_pointer;
/* Temporarily include '@' in symbol names. */
else if (strcmp (typename, "object") == 0
|| strcmp (typename, "STT_OBJECT") == 0)
type = BSF_OBJECT;
+ else if (strcmp (typename, "tls_object") == 0
+ || strcmp (typename, "STT_TLS") == 0)
+ type = BSF_OBJECT | BSF_THREAD_LOCAL;
+ else if (strcmp (typename, "notype") == 0
+ || strcmp (typename, "STT_NOTYPE") == 0)
+ ;
#ifdef md_elf_symbol_type
else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
;
supposed to *EXT to the external symbol information, and return
whether the symbol should be used at all. */
-static boolean
+static bfd_boolean
elf_get_extr (sym, ext)
asymbol *sym;
EXTR *ext;
{
if (sym->udata.p == NULL)
- return false;
+ return FALSE;
*ext = *(EXTR *) sym->udata.p;
- return true;
+ return TRUE;
}
/* This function is called by bfd_ecoff_debug_externals. It has
{
as_bad (_("invalid attempt to declare external version name as default in symbol `%s'"),
sy_obj->versioned_name);
- *puntp = true;
+ *puntp = TRUE;
}
S_SET_NAME (symp, sy_obj->versioned_name);
}
flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_GROUP;
for (s = list.head[i]; s != NULL; s = elf_next_in_group (s))
- if (elf_linkonce_p (s) != ((flags & SEC_LINK_ONCE) != 0))
+ if ((s->flags ^ flags) & SEC_LINK_ONCE)
{
flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
if (s != list.head[i])
as_fatal (_("can't create group: %s"),
bfd_errmsg (bfd_get_error ()));
}
+ elf_section_type (s) = SHT_GROUP;
/* Pass a pointer to the first section in this group. */
elf_next_in_group (s) = list.head[i];
/* Set up the external symbols. */
debug.ssext = debug.ssext_end = NULL;
debug.external_ext = debug.external_ext_end = NULL;
- if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true,
+ if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, TRUE,
elf_get_extr, elf_set_index))
as_fatal (_("failed to set up debugging information: %s"),
bfd_errmsg (bfd_get_error ()));
sec = bfd_get_section_by_name (stdoutput, ".mdebug");
assert (sec != NULL);
- know (stdoutput->output_has_begun == false);
+ know (!stdoutput->output_has_begun);
/* We set the size of the section, call bfd_set_section_contents
to force the ELF backend to allocate a file position, and then
as_fatal (_("can't start writing .mdebug section: %s"),
bfd_errmsg (bfd_get_error ()));
- know (stdoutput->output_has_begun == true);
+ know (stdoutput->output_has_begun);
know (sec->filepos != 0);
if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap,