/* ELF object file format
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
|| (symbol_rootP->bsym->flags & BSF_FILE) == 0)
{
symbolS *sym;
+ unsigned int name_length;
sym = symbol_new (s, absolute_section, 0, NULL);
symbol_set_frag (sym, &zero_address_frag);
+
+ name_length = strlen (s);
+ if (name_length > strlen (S_GET_NAME (sym)))
+ {
+ obstack_grow (¬es, s, name_length + 1);
+ S_SET_NAME (sym, (const char *) obstack_finish (¬es));
+ }
+ else
+ strcpy ((char *) S_GET_NAME (sym), s);
+
symbol_get_bfdsym (sym)->flags |= BSF_FILE;
if (symbol_rootP != sym)
bfdsym = symbol_get_bfdsym (symbolP);
elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
- assert (elfsym);
+ gas_assert (elfsym);
elfsym->internal_elf_sym.st_other &= ~3;
elfsym->internal_elf_sym.st_other |= visibility;
static bfd_boolean
get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
{
- const char *gname = inf;
+ const char *gname = (const char *) inf;
const char *group_name = elf_group_name (sec);
-
+
return (group_name == gname
|| (group_name != NULL
&& gname != NULL
void
obj_elf_change_section (const char *name,
int type,
- int attr,
+ bfd_vma attr,
int entsize,
const char *group_name,
int linkonce,
if (push)
{
struct section_stack *elt;
- elt = xmalloc (sizeof (struct section_stack));
+ elt = (struct section_stack *) xmalloc (sizeof (struct section_stack));
elt->next = section_stack;
elt->seg = now_seg;
elt->prev_seg = previous_section;
{
symbolS *secsym;
+ if (type == SHT_NULL)
+ type = bfd_elf_get_default_section_type (flags);
elf_section_type (sec) = type;
elf_section_flags (sec) = attr;
#endif
}
-static int
+static bfd_vma
obj_elf_parse_section_letters (char *str, size_t len)
{
- int attr = 0;
+ bfd_vma attr = 0;
while (len > 0)
{
{
char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S,G,T");
#ifdef md_elf_section_letter
- int md_attr = md_elf_section_letter (*str, &bad_msg);
- if (md_attr >= 0)
+ bfd_vma md_attr = md_elf_section_letter (*str, &bad_msg);
+ if (md_attr > 0)
attr |= md_attr;
else
#endif
}
static int
-obj_elf_section_word (char *str, size_t len)
-{
- if (len == 5 && strncmp (str, "write", 5) == 0)
- return SHF_WRITE;
- if (len == 5 && strncmp (str, "alloc", 5) == 0)
- 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
- {
- int md_attr = md_elf_section_word (str, len);
- if (md_attr >= 0)
- return md_attr;
- }
-#endif
-
- as_warn (_("unrecognized section attribute"));
- return 0;
-}
-
-static int
-obj_elf_section_type (char *str, size_t len)
+obj_elf_section_type (char *str, size_t len, bfd_boolean warn)
{
if (len == 8 && strncmp (str, "progbits", 8) == 0)
return SHT_PROGBITS;
}
#endif
- as_warn (_("unrecognized section type"));
+ if (warn)
+ as_warn (_("unrecognized section type"));
+ return 0;
+}
+
+static bfd_vma
+obj_elf_section_word (char *str, size_t len, int *type)
+{
+ int ret;
+
+ if (len == 5 && strncmp (str, "write", 5) == 0)
+ return SHF_WRITE;
+ if (len == 5 && strncmp (str, "alloc", 5) == 0)
+ 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
+ {
+ bfd_vma md_attr = md_elf_section_word (str, len);
+ if (md_attr > 0)
+ return md_attr;
+ }
+#endif
+
+ ret = obj_elf_section_type (str, len, FALSE);
+ if (ret != 0)
+ *type = ret;
+ else
+ as_warn (_("unrecognized section attribute"));
+
return 0;
}
return NULL;
}
- name = xmalloc (end - input_line_pointer + 1);
+ name = (char *) 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
obj_elf_section (int push)
{
char *name, *group_name, *beg;
- int type, attr, dummy;
+ int type, dummy;
+ bfd_vma attr;
int entsize;
int linkonce;
+ subsegT new_subsection = -1;
#ifndef TC_I370
if (flag_mri)
++input_line_pointer;
SKIP_WHITESPACE ();
+ if (push && ISDIGIT (*input_line_pointer))
+ {
+ /* .pushsection has an optional subsection. */
+ new_subsection = (subsegT) get_absolute_expression ();
+
+ SKIP_WHITESPACE ();
+
+ /* Stop if we don't see a comma. */
+ if (*input_line_pointer != ',')
+ goto done;
+
+ /* Skip the comma. */
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ }
+
if (*input_line_pointer == '"')
{
beg = demand_copy_C_string (&dummy);
ignore_rest_of_line ();
return;
}
- type = obj_elf_section_type (beg, strlen (beg));
+ type = obj_elf_section_type (beg, strlen (beg), TRUE);
}
else if (c == '@' || c == '%')
{
beg = ++input_line_pointer;
c = get_symbol_end ();
*input_line_pointer = c;
- type = obj_elf_section_type (beg, input_line_pointer - beg);
+ type = obj_elf_section_type (beg, input_line_pointer - beg, TRUE);
}
else
input_line_pointer = save;
c = get_symbol_end ();
*input_line_pointer = c;
- attr |= obj_elf_section_word (beg, input_line_pointer - beg);
+ attr |= obj_elf_section_word (beg, input_line_pointer - beg, & type);
SKIP_WHITESPACE ();
}
}
}
+done:
demand_empty_rest_of_line ();
obj_elf_change_section (name, type, attr, entsize, group_name, linkonce, push);
+
+ if (push && new_subsection != -1)
+ subseg_set (now_seg, new_subsection);
}
/* Change to the .data section. */
static void
obj_elf_subsection (int ignore ATTRIBUTE_UNUSED)
{
- register int temp;
+ int temp;
#ifdef md_flush_pending_output
md_flush_pending_output ();
if (csym == NULL || symbol_get_frag (csym) == NULL)
{
- as_bad ("expected `%s' to have already been set for .vtable_inherit",
+ as_bad (_("expected `%s' to have already been set for .vtable_inherit"),
cname);
bad = 1;
}
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
- as_bad ("expected comma after name in .vtable_inherit");
+ as_bad (_("expected comma after name in .vtable_inherit"));
ignore_rest_of_line ();
return NULL;
}
if (bad)
return NULL;
- assert (symbol_get_value_expression (csym)->X_op == O_constant);
+ gas_assert (symbol_get_value_expression (csym)->X_op == O_constant);
return fix_new (symbol_get_frag (csym),
symbol_get_value_expression (csym)->X_add_number,
0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT);
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
- as_bad ("expected comma after name in .vtable_entry");
+ as_bad (_("expected comma after name in .vtable_entry"));
ignore_rest_of_line ();
return NULL;
}
if (srcelf->size)
{
if (destelf->size == NULL)
- destelf->size = xmalloc (sizeof (expressionS));
+ destelf->size = (expressionS *) xmalloc (sizeof (expressionS));
*destelf->size = *srcelf->size;
}
else
}
else
{
- symbol_get_obj (sym)->size = xmalloc (sizeof (expressionS));
+ symbol_get_obj (sym)->size =
+ (expressionS *) xmalloc (sizeof (expressionS));
*symbol_get_obj (sym)->size = exp;
}
demand_empty_rest_of_line ();
}
/* Handle the ELF .type pseudo-op. This sets the type of a symbol.
- There are five syntaxes:
+ There are six syntaxes:
The first (used on Solaris) is
.type SYM,#function
.type SYM,%function
The fifth (used on SVR4/860) is
.type SYM,"function"
+ The sixth (emitted by recent SunPRO under Solaris) is
+ .type SYM,[0-9]
+ where the integer is the STT_* value.
*/
+static char *
+obj_elf_type_name (char *cp)
+{
+ char *p;
+
+ p = input_line_pointer;
+ if (*input_line_pointer >= '0'
+ && *input_line_pointer <= '9')
+ {
+ while (*input_line_pointer >= '0'
+ && *input_line_pointer <= '9')
+ ++input_line_pointer;
+ *cp = *input_line_pointer;
+ *input_line_pointer = '\0';
+ }
+ else
+ *cp = get_symbol_end ();
+
+ return p;
+}
+
static void
obj_elf_type (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char c;
int type;
- const char *typename;
+ const char *type_name;
symbolS *sym;
elf_symbol_type *elfsym;
|| *input_line_pointer == '%')
++input_line_pointer;
- typename = input_line_pointer;
- c = get_symbol_end ();
+ type_name = obj_elf_type_name (& c);
type = 0;
- if (strcmp (typename, "function") == 0
- || strcmp (typename, "STT_FUNC") == 0)
+ if (strcmp (type_name, "function") == 0
+ || strcmp (type_name, "2") == 0
+ || strcmp (type_name, "STT_FUNC") == 0)
type = BSF_FUNCTION;
- else if (strcmp (typename, "object") == 0
- || strcmp (typename, "STT_OBJECT") == 0)
+ else if (strcmp (type_name, "object") == 0
+ || strcmp (type_name, "1") == 0
+ || strcmp (type_name, "STT_OBJECT") == 0)
type = BSF_OBJECT;
- else if (strcmp (typename, "tls_object") == 0
- || strcmp (typename, "STT_TLS") == 0)
+ else if (strcmp (type_name, "tls_object") == 0
+ || strcmp (type_name, "6") == 0
+ || strcmp (type_name, "STT_TLS") == 0)
type = BSF_OBJECT | BSF_THREAD_LOCAL;
- else if (strcmp (typename, "notype") == 0
- || strcmp (typename, "STT_NOTYPE") == 0)
+ else if (strcmp (type_name, "notype") == 0
+ || strcmp (type_name, "0") == 0
+ || strcmp (type_name, "STT_NOTYPE") == 0)
;
+ else if (strcmp (type_name, "common") == 0
+ || strcmp (type_name, "5") == 0
+ || strcmp (type_name, "STT_COMMON") == 0)
+ {
+ type = BSF_OBJECT;
+
+ if (! S_IS_COMMON (sym))
+ {
+ if (S_IS_VOLATILE (sym))
+ {
+ sym = symbol_clone (sym, 1);
+ S_SET_SEGMENT (sym, bfd_com_section_ptr);
+ S_SET_VALUE (sym, 0);
+ S_SET_EXTERNAL (sym);
+ symbol_set_frag (sym, &zero_address_frag);
+ S_CLEAR_VOLATILE (sym);
+ }
+ else if (S_IS_DEFINED (sym) || symbol_equated_p (sym))
+ as_bad (_("symbol '%s' is already defined"), S_GET_NAME (sym));
+ else
+ {
+ /* FIXME: Is it safe to just change the section ? */
+ S_SET_SEGMENT (sym, bfd_com_section_ptr);
+ S_SET_VALUE (sym, 0);
+ S_SET_EXTERNAL (sym);
+ }
+ }
+ }
+ else if (strcmp (type_name, "gnu_indirect_function") == 0
+ || 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_LINUX
+ /* GNU/Linux is still using the default value 0. */
+ || bed->elf_osabi == ELFOSABI_NONE))
+ as_bad (_("symbol type \"%s\" is supported only by GNU targets"),
+ type_name);
+ 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_LINUX
+ /* GNU/Linux is still using the default value 0. */
+ || bed->elf_osabi == ELFOSABI_NONE))
+ as_bad (_("symbol type \"%s\" is supported only by GNU targets"),
+ type_name);
+ type = BSF_OBJECT | BSF_GNU_UNIQUE;
+ /* PR 10549: Always set OSABI field to LINUX for objects containing unique symbols. */
+ bed->elf_osabi = ELFOSABI_LINUX;
+ }
#ifdef md_elf_symbol_type
- else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
+ else if ((type = md_elf_symbol_type (type_name, sym, elfsym)) != -1)
;
#endif
else
- as_bad (_("unrecognized symbol type \"%s\""), typename);
+ as_bad (_("unrecognized symbol type \"%s\""), type_name);
*input_line_pointer = c;
char *p;
comment_section = subseg_new (".comment", 0);
bfd_set_section_flags (stdoutput, comment_section,
- SEC_READONLY | SEC_HAS_CONTENTS);
+ SEC_READONLY | SEC_HAS_CONTENTS
+ | SEC_MERGE | SEC_STRINGS);
+ comment_section->entsize = 1;
+#ifdef md_elf_section_change_hook
+ md_elf_section_change_hook ();
+#endif
p = frag_more (1);
*p = 0;
}
else
subseg_set (comment_section, 0);
- stringer (1);
+ stringer (8 + 1);
subseg_set (old_section, old_subsection);
}
/* Zero it out. */
memset (p, 0, 12);
as_where (&file, NULL);
- stabstr_name = xmalloc (strlen (segment_name (seg)) + 4);
+ stabstr_name = (char *) xmalloc (strlen (segment_name (seg)) + 4);
strcpy (stabstr_name, segment_name (seg));
strcat (stabstr_name, "str");
stroff = get_stab_string_offset (file, stabstr_name);
if (!strcmp ("str", sec->name + strlen (sec->name) - 3))
return;
- name = alloca (strlen (sec->name) + 4);
+ name = (char *) alloca (strlen (sec->name) + 4);
strcpy (name, sec->name);
strcat (name, "str");
strsec = bfd_get_section_by_name (abfd, name);
nsyms = bfd_section_size (abfd, sec) / 12 - 1;
p = seg_info (sec)->stabu.p;
- assert (p != 0);
+ gas_assert (p != 0);
bfd_h_put_16 (abfd, nsyms, p + 6);
bfd_h_put_32 (abfd, strsz, p + 8);
static void
build_group_lists (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
{
- struct group_list *list = inf;
+ struct group_list *list = (struct group_list *) inf;
const char *group_name = elf_group_name (sec);
unsigned int i;
if ((i & 127) == 0)
{
unsigned int newsize = i + 128;
- list->head = xrealloc (list->head, newsize * sizeof (*list->head));
- list->elt_count = xrealloc (list->elt_count,
- newsize * sizeof (*list->elt_count));
+ list->head = (asection **) xrealloc (list->head,
+ newsize * sizeof (*list->head));
+ list->elt_count = (unsigned int *)
+ xrealloc (list->elt_count, newsize * sizeof (*list->elt_count));
}
list->head[i] = sec;
list->elt_count[i] = 1;
bfd_errmsg (bfd_get_error ()));
sec = bfd_get_section_by_name (stdoutput, ".mdebug");
- assert (sec != NULL);
+ gas_assert (sec != NULL);
know (!stdoutput->output_has_begun);