/* ELF object file format
- Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000
+ Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
};
void
-obj_elf_change_section (name, type, attr, push)
+obj_elf_change_section (name, type, attr, entsize, push)
char *name;
- int type, attr, push;
+ int type, attr, entsize, push;
{
asection *old_sec;
segT sec;
| ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
| ((attr & SHF_ALLOC) ? SEC_ALLOC : 0)
| (((attr & SHF_ALLOC) && type != SHT_NOBITS) ? SEC_LOAD : 0)
- | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0));
+ | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0)
+ | ((attr & SHF_MERGE) ? SEC_MERGE : 0)
+ | ((attr & SHF_STRINGS) ? SEC_STRINGS : 0));
#ifdef md_elf_section_flags
flags = md_elf_section_flags (flags, attr, type);
#endif
seg_info (sec)->bss = 1;
bfd_set_section_flags (stdoutput, sec, flags);
+ if (flags & SEC_MERGE)
+ sec->entsize = entsize;
/* Add a symbol for this section to the symbol table. */
secsym = symbol_find (name);
saw the first time. */
if ((old_sec->flags ^ flags)
& (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
- | SEC_EXCLUDE | SEC_SORT_ENTRIES))
+ | SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS))
as_warn (_("Ignoring changed section attributes for %s"), name);
+ else if ((flags & SEC_MERGE) && old_sec->entsize != entsize)
+ as_warn (_("Ignoring changed section entity size for %s"), name);
}
#ifdef md_elf_section_change_hook
case 'x':
attr |= SHF_EXECINSTR;
break;
+ case 'm':
+ attr |= SHF_MERGE;
+ break;
+ case 's':
+ attr |= SHF_STRINGS;
+ break;
default:
{
- char *bad_msg = _("Unrecognized .section attribute: want a,w,x");
+ char *bad_msg = _("Unrecognized .section attribute: want a,m,s,w,x");
#ifdef md_elf_section_letter
int md_attr = md_elf_section_letter (*str, &bad_msg);
if (md_attr >= 0)
{
char *name, *beg, *end;
int type, attr, dummy;
+ int entsize;
#ifndef TC_I370
if (flag_mri)
type = SHT_NULL;
attr = 0;
+ entsize = 0;
if (*input_line_pointer == ',')
{
type = obj_elf_section_type (beg, input_line_pointer - beg);
}
}
+
+ SKIP_WHITESPACE ();
+ if ((attr & SHF_MERGE) && *input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ entsize = get_absolute_expression ();
+ if (entsize < 0)
+ {
+ as_warn (_("Bad .section directive - invalid merge entity size"));
+ attr &= ~SHF_MERGE;
+ entsize = 0;
+ }
+ }
}
else
{
demand_empty_rest_of_line ();
- obj_elf_change_section (name, type, attr, push);
+ if ((attr & SHF_MERGE) && entsize == 0)
+ {
+ as_warn (_("Entity size for SHF_MERGE not specified.\nSpecify entity size as 4th argument"));
+ attr &= SHF_MERGE;
+ }
+
+#ifdef md_elf_section_change_data_hook
+ md_elf_section_change_data_hook (name, type, attr, entsize, push);
+#endif
+
+ obj_elf_change_section (name, type, attr, entsize, push);
}
/* Change to the .data section. */
*input_line_pointer = c;
if (strchr (symbol_get_obj (sym)->versioned_name,
- ELF_VER_CHR) == NULL)
+ ELF_VER_CHR) == NULL)
{
as_bad (_("missing version name in `%s' for symbol `%s'"),
symbol_get_obj (sym)->versioned_name,
if (sy_obj->versioned_name != NULL)
{
+ char *p;
+
+ p = strchr (sy_obj->versioned_name, ELF_VER_CHR);
+ know (p != NULL);
+
/* This symbol was given a new name with the .symver directive.
If this is an external reference, just rename the symbol to
if (! S_IS_DEFINED (symp))
{
- char *p;
-
/* Verify that the name isn't using the @@ syntax--this is
reserved for definitions of the default version to link
against. */
- p = strchr (sy_obj->versioned_name, ELF_VER_CHR);
- know (p != NULL);
if (p[1] == ELF_VER_CHR)
{
as_bad (_("invalid attempt to declare external version name as default in symbol `%s'"),
}
else
{
- symbolS *symp2;
+ if (p [1] == ELF_VER_CHR && p [2] == ELF_VER_CHR)
+ {
+ size_t l;
+
+ /* The @@@ syntax is a special case. It renames the
+ symbol name to versioned_name with one `@' removed. */
+ l = strlen (&p[3]) + 1;
+ memmove (&p [2], &p[3], l);
+ S_SET_NAME (symp, sy_obj->versioned_name);
+ }
+ else
+ {
+ symbolS *symp2;
- /* FIXME: Creating a new symbol here is risky. We're in the
- final loop over the symbol table. We can get away with
- it only because the symbol goes to the end of the list,
- where the loop will still see it. It would probably be
- better to do this in obj_frob_file_before_adjust. */
+ /* FIXME: Creating a new symbol here is risky. We're
+ in the final loop over the symbol table. We can
+ get away with it only because the symbol goes to
+ the end of the list, where the loop will still see
+ it. It would probably be better to do this in
+ obj_frob_file_before_adjust. */
- symp2 = symbol_find_or_make (sy_obj->versioned_name);
+ symp2 = symbol_find_or_make (sy_obj->versioned_name);
- /* Now we act as though we saw symp2 = sym. */
+ /* Now we act as though we saw symp2 = sym. */
- S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
+ S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
- /* Subtracting out the frag address here is a hack because
- we are in the middle of the final loop. */
- S_SET_VALUE (symp2,
- (S_GET_VALUE (symp)
- - symbol_get_frag (symp)->fr_address));
+ /* Subtracting out the frag address here is a hack
+ because we are in the middle of the final loop. */
+ S_SET_VALUE (symp2,
+ (S_GET_VALUE (symp)
+ - symbol_get_frag (symp)->fr_address));
- symbol_set_frag (symp2, symbol_get_frag (symp));
+ symbol_set_frag (symp2, symbol_get_frag (symp));
- /* This will copy over the size information. */
- copy_symbol_attributes (symp2, symp);
+ /* This will copy over the size information. */
+ copy_symbol_attributes (symp2, symp);
- if (S_IS_WEAK (symp))
- S_SET_WEAK (symp2);
+ if (S_IS_WEAK (symp))
+ S_SET_WEAK (symp2);
- if (S_IS_EXTERNAL (symp))
- S_SET_EXTERNAL (symp2);
+ if (S_IS_EXTERNAL (symp))
+ S_SET_EXTERNAL (symp2);
+ }
}
}
#endif
}
-/* It removes any unneeded versioned symbols from the symbol table. */
+/* It removes any unneeded versioned symbols from the symbol table. */
void
elf_frob_file_before_adjust ()
symbolS *symp;
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
- if (symbol_get_obj (symp)->versioned_name
- && !S_IS_DEFINED (symp)
- && symbol_used_p (symp) == 0
- && symbol_used_in_reloc_p (symp) == 0)
- symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+ if (symbol_get_obj (symp)->versioned_name)
+ {
+ if (!S_IS_DEFINED (symp))
+ {
+ char *p;
+
+ /* The @@@ syntax is a special case. If the symbol is
+ not defined, 2 `@'s will be removed from the
+ versioned_name. */
+
+ p = strchr (symbol_get_obj (symp)->versioned_name,
+ ELF_VER_CHR);
+ know (p != NULL);
+ if (p [1] == ELF_VER_CHR && p [2] == ELF_VER_CHR)
+ {
+ size_t l = strlen (&p[3]) + 1;
+ memmove (&p [1], &p[3], l);
+ }
+ if (symbol_used_p (symp) == 0
+ && symbol_used_in_reloc_p (symp) == 0)
+ symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+ }
+ }
}
}