This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

SHT_GROUP support, part 1


This is the first part, assembler support, towards providing ELF
SHT_GROUP support in gas and ld.  Posted now so that interested people
can review, and correct any silly errors I might have made.  I'll
probably start writing the linker support tomorrow.

bfd/ChangeLog
	* elf-bfd.h (struct bfd_elf_section_data): Add "group" and
	"next_in_group".
	* elf.c (_bfd_elf_make_section_from_shdr): Set BFD group flag.
	(elf_fake_sections): Set header type for SEC_GROUP, and header
	flags for sections in a group.
	(set_group_contents): New function.
	(_bfd_elf_compute_section_file_positions): Call it.
	(assign_section_numbers): Set sh_link for SHT_GROUP.
	* section.c (SEC_GROUP): Define.
	(struct sec): Comment fixes.
	* bfd-in2.h: Regenerate.

gas/ChangeLog
	* config/obj-elf.c: (obj_elf_change_section): Add "group" param.
	Set elf_section_data group from it.  Warn if group name changed.
	(obj_elf_parse_section_letters): Parse 'G' too.
	(obj_elf_section): Parse group name.
	(struct group_list): New.
	(build_group_lists): New function.
	(elf_frob_file): Create SEC_GROUP section(s).

-- 
Alan Modra

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.50
diff -u -p -r1.50 elf-bfd.h
--- elf-bfd.h	2001/10/04 12:30:26	1.50
+++ elf-bfd.h	2001/10/07 06:20:05
@@ -815,6 +815,12 @@ struct bfd_elf_section_data
   /* A pointer used for SEC_MERGE optimizations.  */
   PTR merge_info;
 
+  /* Group name, if this section is part of a group.  */
+  const char *group;
+
+  /* A linked list of sections in the group.  */
+  asection *next_in_group;
+
   /* A pointer available for the processor specific ELF backend.  */
   PTR tdata;
 
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.97
diff -u -p -r1.97 elf.c
--- elf.c	2001/10/03 08:33:18	1.97
+++ elf.c	2001/10/07 06:20:09
@@ -52,6 +52,7 @@ static boolean swap_out_syms PARAMS ((bf
 static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *));
 static char *elf_read PARAMS ((bfd *, file_ptr, bfd_size_type));
 static void elf_fake_sections PARAMS ((bfd *, asection *, PTR));
+static void set_group_contents PARAMS ((bfd *, asection *, PTR));
 static boolean assign_section_numbers PARAMS ((bfd *));
 static INLINE int sym_is_global PARAMS ((bfd *, asymbol *));
 static boolean elf_map_symbols PARAMS ((bfd *));
@@ -380,6 +381,8 @@ _bfd_elf_make_section_from_shdr (abfd, h
   flags = SEC_NO_FLAGS;
   if (hdr->sh_type != SHT_NOBITS)
     flags |= SEC_HAS_CONTENTS;
+  if (hdr->sh_type == SHT_GROUP)
+    flags |= SEC_GROUP;
   if ((hdr->sh_flags & SHF_ALLOC) != 0)
     {
       flags |= SEC_ALLOC;
@@ -1847,6 +1850,11 @@ elf_fake_sections (abfd, asect, failedpt
 	BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0
 		    || this_hdr->sh_info == elf_tdata (abfd)->cverrefs);
     }
+  else if ((asect->flags & SEC_GROUP) != 0)
+    {
+      this_hdr->sh_type = SHT_GROUP;
+      this_hdr->sh_entsize = 4;
+    }
   else if ((asect->flags & SEC_ALLOC) != 0
 	   && ((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0))
     this_hdr->sh_type = SHT_NOBITS;
@@ -1866,6 +1874,8 @@ elf_fake_sections (abfd, asect, failedpt
       if ((asect->flags & SEC_STRINGS) != 0)
 	this_hdr->sh_flags |= SHF_STRINGS;
     }
+  if (elf_section_data (asect)->group != NULL)
+    this_hdr->sh_flags |= SHF_GROUP;
 
   /* Check for processor-specific section types.  */
   if (bed->elf_backend_fake_sections)
@@ -1883,6 +1893,43 @@ elf_fake_sections (abfd, asect, failedpt
     *failedptr = true;
 }
 
+static void
+set_group_contents (abfd, sec, failedptrarg)
+     bfd *abfd;
+     asection *sec;
+     PTR failedptrarg ATTRIBUTE_UNUSED;
+{
+  asection *elt;
+  unsigned char *loc;
+
+  if (elf_section_data (sec)->this_hdr.sh_type != SHT_GROUP)
+    return;
+
+  elf_section_data (sec)->this_hdr.sh_info =
+    elf_section_syms (abfd)[sec->index]->udata.i;
+
+  /* Get the pointer to the first section in the group that we
+     squirreled away here.  */
+  elt = (asection *) sec->lineno;
+
+  loc = sec->contents + sec->_raw_size;
+
+  /* First element is a flag word.  Rest of section is elf section
+     indices for all the sections of the group.  Write them backwards
+     just to keep the group in the same order as given in .section
+     directives, not that it matters.  */
+  while (elt != NULL)
+    {
+      loc -= 4;
+      H_PUT_32 (abfd, elf_section_data (elt)->this_idx, loc);
+      elt = elf_section_data (elt)->next_in_group;
+    }
+  loc -= 4;
+  H_PUT_32 (abfd, 0, loc);
+
+  BFD_ASSERT (loc == sec->contents);
+}
+
 /* Assign all ELF section numbers.  The dummy first section is handled here
    too.  The link/info pointers for the standard section types are filled
    in here too, while we're at it.  */
@@ -2055,6 +2102,9 @@ assign_section_numbers (abfd)
 	  if (s != NULL)
 	    d->this_hdr.sh_link = elf_section_data (s)->this_idx;
 	  break;
+
+	case SHT_GROUP:
+	  d->this_hdr.sh_link = t->symtab_section;
 	}
     }
 
@@ -2328,6 +2378,10 @@ _bfd_elf_compute_section_file_positions 
       int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC));
 
       if (! swap_out_syms (abfd, &strtab, relocatable_p))
+	return false;
+
+      bfd_map_over_sections (abfd, set_group_contents, &failed);
+      if (failed)
 	return false;
     }
 
Index: bfd/section.c
===================================================================
RCS file: /cvs/src/src/bfd/section.c,v
retrieving revision 1.36
diff -u -p -r1.36 section.c
--- section.c	2001/09/29 12:07:00	1.36
+++ section.c	2001/10/07 06:20:11
@@ -177,7 +177,7 @@ CODE_FRAGMENT
 .
 .  int id;
 .
-.  {* Which section is it; 0..nth.  *}
+.  {* Which section in the bfd; 0..n-1 as sections are created in a bfd.  *}
 .
 .  int index;
 .
@@ -292,9 +292,10 @@ CODE_FRAGMENT
 .     objects are to be further relocated.  *}
 .#define SEC_EXCLUDE 0x40000
 .
-.  {* The contents of this section are to be sorted by the
-.     based on the address specified in the associated symbol
-.     table.  *}
+.  {* The contents of this section are to be sorted based on the sum of
+.     the symbol and addend values specified by the associated relocation
+.     entries.  Entries without associated relocation entries will be
+.     appended to the end of the section in an unspecified order.  *}
 .#define SEC_SORT_ENTRIES 0x80000
 .
 .  {* When linking, duplicate sections of the same name should be
@@ -361,6 +362,9 @@ CODE_FRAGMENT
 .     size entries.  *}
 .#define SEC_STRINGS 0x40000000
 .
+.  {* This section contains data about section groups.  *}
+.#define SEC_GROUP 0x80000000
+.
 .  {*  End of section flags.  *}
 .
 .  {* Some internal packed boolean fields.  *}
@@ -381,7 +385,8 @@ CODE_FRAGMENT
 .  {* A mark flag used by some linker backends for garbage collection.  *}
 .  unsigned int gc_mark : 1;
 .
-.  {* Used by the ELF code to mark sections which have been allocated to segments.  *}
+.  {* Used by the ELF code to mark sections which have been allocated
+.     to segments.  *}
 .  unsigned int segment_mark : 1;
 .
 .  {* End of internal packed boolean fields.  *}
Index: gas/config/obj-elf.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-elf.c,v
retrieving revision 1.41
diff -u -p -r1.41 obj-elf.c
--- obj-elf.c	2001/10/07 06:16:54	1.41
+++ obj-elf.c	2001/10/07 06:20:12
@@ -58,6 +58,7 @@ static void elf_s_set_align PARAMS ((sym
 static void elf_s_set_other PARAMS ((symbolS *, int));
 static int elf_sec_sym_ok_for_reloc PARAMS ((asection *));
 static void adjust_stab_sections PARAMS ((bfd *, asection *, PTR));
+static void build_group_lists PARAMS ((bfd *, asection *, PTR));
 static int elf_separate_stab_sections PARAMS ((void));
 static void elf_init_stab_section PARAMS ((segT));
 
@@ -74,7 +75,8 @@ static void obj_elf_ident PARAMS ((int))
 static void obj_elf_weak PARAMS ((int));
 static void obj_elf_local PARAMS ((int));
 static void obj_elf_visibility PARAMS ((int));
-static void obj_elf_change_section PARAMS ((char *, int, int, int, int));
+static void obj_elf_change_section
+  PARAMS ((const char *, int, int, int, const char *, int));
 static int obj_elf_parse_section_letters PARAMS ((char *, size_t));
 static int obj_elf_section_word PARAMS ((char *, size_t));
 static char *obj_elf_section_name PARAMS ((void));
@@ -618,9 +620,13 @@ static struct special_section const spec
 };
 
 static void
-obj_elf_change_section (name, type, attr, entsize, push)
-     char *name;
-     int type, attr, entsize, push;
+obj_elf_change_section (name, type, attr, entsize, group, push)
+     const char *name;
+     int type;
+     int attr;
+     int entsize;
+     const char *group;
+     int push;
 {
   asection *old_sec;
   segT sec;
@@ -706,6 +712,7 @@ obj_elf_change_section (name, type, attr
       bfd_set_section_flags (stdoutput, sec, flags);
       if (flags & SEC_MERGE)
 	sec->entsize = entsize;
+      elf_section_data (sec)->group = group;
 
       /* Add a symbol for this section to the symbol table.  */
       secsym = symbol_find (name);
@@ -725,6 +732,9 @@ obj_elf_change_section (name, type, attr
 	as_warn (_("ignoring changed section attributes for %s"), name);
       else if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
 	as_warn (_("ignoring changed section entity size for %s"), name);
+      else if ((attr & SHF_GROUP) != 0
+	       && strcmp (elf_section_data (old_sec)->group, group) != 0)
+	as_warn (_("ignoring new section group for %s"), name);
     }
 
 #ifdef md_elf_section_change_hook
@@ -758,6 +768,9 @@ obj_elf_parse_section_letters (str, len)
 	case 'S':
 	  attr |= SHF_STRINGS;
 	  break;
+	case 'G':
+	  attr |= SHF_GROUP;
+	  break;
 	/* Compatibility.  */
 	case 'm':
 	  if (*(str - 1) == 'a')
@@ -772,7 +785,7 @@ obj_elf_parse_section_letters (str, len)
 	    }
 	default:
 	  {
-	    char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S");
+	    char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S,G");
 #ifdef md_elf_section_letter
 	    int md_attr = md_elf_section_letter (*str, &bad_msg);
 	    if (md_attr >= 0)
@@ -882,7 +895,7 @@ void
 obj_elf_section (push)
      int push;
 {
-  char *name, *beg;
+  char *name, *group, *beg;
   int type, attr, dummy;
   int entsize;
 
@@ -913,6 +926,7 @@ obj_elf_section (push)
     return;
   type = SHT_NULL;
   attr = 0;
+  group = NULL;
   entsize = 0;
 
   if (*input_line_pointer == ',')
@@ -976,6 +990,19 @@ obj_elf_section (push)
 	      as_warn (_("entity size for SHF_MERGE not specified"));
 	      attr &= ~SHF_MERGE;
 	    }
+	  
+	  if ((attr & SHF_GROUP) != 0 && *input_line_pointer == ',')
+	    {
+	      ++input_line_pointer;
+	      group = obj_elf_section_name ();
+	      if (group == NULL)
+		attr &= ~SHF_GROUP;
+	    }
+	  else if ((attr & SHF_GROUP) != 0)
+	    {
+	      as_warn (_("group name for SHF_GROUP not specified"));
+	      attr &= ~SHF_GROUP;
+	    }
 	}
       else
 	{
@@ -1005,7 +1032,7 @@ obj_elf_section (push)
 
   demand_empty_rest_of_line ();
 
-  obj_elf_change_section (name, type, attr, entsize, push);
+  obj_elf_change_section (name, type, attr, entsize, group, push);
 }
 
 /* Change to the .data section.  */
@@ -1860,10 +1887,90 @@ elf_frob_symbol (symp, puntp)
 #endif
 }
 
+struct group_list
+{
+  asection **member;
+  unsigned int *in_group;
+  unsigned int count;
+};
+
+static void
+build_group_lists (abfd, sec, inf)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *sec;
+     PTR inf;
+{
+  struct group_list *list = (struct group_list *) inf;
+  const char *group_name = elf_section_data (sec)->group;
+  unsigned int i;
+
+  if (group_name == NULL)
+    return;
+
+  for (i = 0; i < list->count; i++)
+    {
+      if (strcmp (group_name, elf_section_data (list->member[i])->group) == 0)
+	{
+	  elf_section_data (sec)->next_in_group = list->member[i];
+	  list->member[i] = sec;
+	  list->in_group[i] += 1;
+	  return;
+	}
+    }
+
+  i = list->count;
+  if ((i & 127) == 0)
+    {
+      unsigned int newsize = i + 128;
+      list->member = xrealloc (list->member,
+			       newsize * sizeof (*list->member));
+      list->in_group = xrealloc (list->in_group,
+				 newsize * sizeof (*list->in_group));
+    }
+  list->member[i] = sec;
+  list->in_group[i] += 1;
+  list->count += 1;
+}
+
 void
 elf_frob_file ()
 {
+  struct group_list group_info;
+  unsigned int i;
+
   bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
+
+  group_info.count = 0;
+  group_info.member = NULL;
+  group_info.in_group = NULL;
+  bfd_map_over_sections (stdoutput, build_group_lists, (PTR) &group_info);
+
+  for (i = 0; i < group_info.count; i++)
+    {
+      const char *group_name = elf_section_data (group_info.member[i])->group;
+      asection *s;
+      flagword flags;
+
+      s = subseg_force_new (group_name, 0);
+      flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_GROUP;
+      if (s == NULL
+	  || ! bfd_set_section_flags (stdoutput, s, flags)
+	  || ! bfd_set_section_alignment (stdoutput, s, 2))
+	{
+	  as_fatal (_("can't create group: %s"),
+		    bfd_errmsg (bfd_get_error ()));
+	}
+
+      /* Pass a pointer to the first section in this group.  This
+	 seems as good a field to use as any;  It's not used otherwise
+	 by the ELF code.  We can't set up the section contents here
+	 yet, because elf section indices have yet to be calculated.  */
+      s->lineno = (alent *) group_info.member[i];
+
+      s->_raw_size = 4 * (group_info.in_group[i] + 1);
+      s->contents = frag_more (s->_raw_size);
+      frag_now->fr_fix = frag_now_fix_octets ();
+    }
 
 #ifdef elf_tc_final_processing
   elf_tc_final_processing ();


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]