+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ /* Switch to the section, creating it if necessary. */
+ if (push)
+ {
+ struct section_stack *elt;
+ elt = xmalloc (sizeof (struct section_stack));
+ elt->next = section_stack;
+ elt->seg = now_seg;
+ elt->prev_seg = previous_section;
+ elt->subseg = now_subseg;
+ elt->prev_subseg = previous_subsection;
+ section_stack = elt;
+ }
+ previous_section = now_seg;
+ previous_subsection = now_subseg;
+
+ new_sec = bfd_get_section_by_name (stdoutput, name) == NULL;
+ sec = subseg_new (name, 0);
+
+ if (new_sec)
+ {
+ flagword flags;
+ symbolS *secsym;
+ int i;
+
+ /* 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)
+ as_warn (_("Setting incorrect section type for %s"), name);
+
+ if ((attr &~ special_sections[i].attributes) != 0)
+ {
+ /* 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)
+ as_warn (_("Setting incorrect section attributes for %s"),
+ name);
+ }
+ attr |= special_sections[i].attributes;
+ break;
+ }
+
+ /* Convert ELF type and flags to BFD flags. */
+ flags = (SEC_RELOC
+ | ((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));
+#ifdef md_elf_section_flags
+ flags = md_elf_section_flags (flags, attr, type);
+#endif
+
+ /* Prevent SEC_HAS_CONTENTS from being inadvertently set. */
+ if (type == SHT_NOBITS)
+ seg_info (sec)->bss = 1;
+
+ bfd_set_section_flags (stdoutput, sec, flags);
+
+ /* Add a symbol for this section to the symbol table. */
+ secsym = symbol_find (name);
+ if (secsym != NULL)
+ symbol_set_bfdsym (secsym, sec->symbol);
+ else
+ symbol_table_insert (section_symbol (sec));
+ }
+
+#ifdef md_elf_section_change_hook
+ md_elf_section_change_hook ();
+#endif
+}
+
+int
+obj_elf_parse_section_letters (str, len)
+ char *str;
+ size_t len;
+{
+ int attr = 0;
+
+ while (len > 0)
+ {
+ switch (*str)
+ {
+ case 'a':
+ attr |= SHF_ALLOC;
+ break;
+ case 'w':
+ attr |= SHF_WRITE;
+ break;
+ case 'x':
+ attr |= SHF_EXECINSTR;
+ break;
+ default:
+ {
+ char *bad_msg = _("Unrecognized .section attribute: want a,w,x");
+#ifdef md_elf_section_letter
+ int md_attr = md_elf_section_letter (*str, &bad_msg);
+ if (md_attr >= 0)
+ attr |= md_attr;
+ else
+#endif
+ {
+ as_warn ("%s", bad_msg);
+ attr = -1;
+ }
+ }
+ break;
+ }
+ str++, len--;
+ }
+
+ return attr;
+}
+
+int
+obj_elf_section_word (str, len)
+ 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;
+
+#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;
+}
+
+int
+obj_elf_section_type (str, len)
+ char *str;
+ size_t len;
+{
+ if (len == 8 && strncmp (str, "progbits", 8) == 0)
+ return SHT_PROGBITS;
+ if (len == 6 && strncmp (str, "nobits", 6) == 0)
+ return SHT_NOBITS;
+
+#ifdef md_elf_section_type
+ {
+ int md_type = md_elf_section_type (str, len);
+ if (md_type >= 0)
+ return md_type;
+ }
+#endif
+
+ as_warn (_("Unrecognized section type"));
+ return 0;
+}
+
+void
+obj_elf_section (push)
+ int push;
+{
+ char *name, *beg, *end;
+ int type, attr, dummy;
+
+#ifndef TC_I370
+ if (flag_mri)
+ {
+ char mri_type;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ previous_section = now_seg;
+ previous_subsection = now_subseg;
+
+ s_mri_sect (&mri_type);
+
+#ifdef md_elf_section_change_hook
+ md_elf_section_change_hook ();
+#endif
+
+ return;
+ }
+#endif /* ! defined (TC_I370) */