Support ELF SHF_GNU_MBIND and PT_GNU_MBIND_XXX
[deliverable/binutils-gdb.git] / gas / config / obj-elf.c
index 1d59fc0296093b453d6aef5a5a503daadf6f44c6..3696d5ea5e274bcc8d96594a1b520db090214b02 100644 (file)
@@ -520,16 +520,26 @@ struct section_stack
 
 static struct section_stack *section_stack;
 
+/* Match both section group name and the sh_info field.  */
+struct section_match
+{
+  const char *group_name;
+  unsigned int info;
+};
+
 static bfd_boolean
 get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
 {
-  const char *gname = (const char *) inf;
+  struct section_match *match = (struct section_match *) inf;
+  const char *gname = match->group_name;
   const char *group_name = elf_group_name (sec);
+  unsigned int info = elf_section_data (sec)->this_hdr.sh_info;
 
-  return (group_name == gname
-         || (group_name != NULL
-             && gname != NULL
-             && strcmp (group_name, gname) == 0));
+  return (info == match->info
+         && (group_name == gname
+             || (group_name != NULL
+                 && gname != NULL
+                 && strcmp (group_name, gname) == 0)));
 }
 
 /* Handle the .section pseudo-op.  This code supports two different
@@ -553,6 +563,7 @@ get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
 void
 obj_elf_change_section (const char *name,
                        unsigned int type,
+                       unsigned int info,
                        bfd_vma attr,
                        int entsize,
                        const char *group_name,
@@ -564,6 +575,7 @@ obj_elf_change_section (const char *name,
   flagword flags;
   const struct elf_backend_data *bed;
   const struct bfd_elf_special_section *ssect;
+  struct section_match match;
 
 #ifdef md_flush_pending_output
   md_flush_pending_output ();
@@ -584,8 +596,10 @@ obj_elf_change_section (const char *name,
   previous_section = now_seg;
   previous_subsection = now_subseg;
 
+  match.group_name = group_name;
+  match.info = info;
   old_sec = bfd_get_section_by_name_if (stdoutput, name, get_section,
-                                       (void *) group_name);
+                                       (void *) &match);
   if (old_sec)
     {
       sec = old_sec;
@@ -695,6 +709,9 @@ obj_elf_change_section (const char *name,
        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)
@@ -720,6 +737,7 @@ obj_elf_change_section (const char *name,
        type = bfd_elf_get_default_section_type (flags);
       elf_section_type (sec) = type;
       elf_section_flags (sec) = attr;
+      elf_section_data (sec)->this_hdr.sh_info = info;
 
       /* Prevent SEC_HAS_CONTENTS from being inadvertently set.  */
       if (type == SHT_NOBITS)
@@ -803,6 +821,9 @@ obj_elf_parse_section_letters (char *str, size_t len, bfd_boolean *is_clone)
        case 'T':
          attr |= SHF_TLS;
          break;
+       case 'd':
+         attr |= SHF_GNU_MBIND;
+         break;
        case '?':
          *is_clone = TRUE;
          break;
@@ -996,6 +1017,7 @@ obj_elf_section (int push)
   int entsize;
   int linkonce;
   subsegT new_subsection = -1;
+  unsigned int info = 0;
 
 #ifndef TC_I370
   if (flag_mri)
@@ -1159,6 +1181,23 @@ obj_elf_section (int push)
                  linkonce = (now_seg->flags & SEC_LINK_ONCE) != 0;
                }
            }
+
+         if ((attr & SHF_GNU_MBIND) != 0 && *input_line_pointer == ',')
+           {
+             ++input_line_pointer;
+             SKIP_WHITESPACE ();
+             if (ISDIGIT (* input_line_pointer))
+               {
+                 char *t = input_line_pointer;
+                 info = strtoul (input_line_pointer,
+                                 &input_line_pointer, 0);
+                 if (info == (unsigned int) -1)
+                   {
+                     as_warn (_("unsupported mbind section info: %s"), t);
+                     info = 0;
+                   }
+               }
+           }
        }
       else
        {
@@ -1189,7 +1228,8 @@ obj_elf_section (int push)
 done:
   demand_empty_rest_of_line ();
 
-  obj_elf_change_section (name, type, attr, entsize, group_name, linkonce, push);
+  obj_elf_change_section (name, type, info, attr, entsize, group_name,
+                         linkonce, push);
 
   if (push && new_subsection != -1)
     subseg_set (now_seg, new_subsection);
This page took 0.029393 seconds and 4 git commands to generate.