This is the mail archive of the binutils@sourceware.org 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]
Other format: [Raw text]

add COMDAT group support for Xtensa


I've committed this patch to add support for COMDAT groups on Xtensa targets. There is an associated patch for GCC that I will add soon. I've tested this by running the binutils testsuite for an xtensa-elf target and also by running the GCC testsuite using binutils with this patch.

The patch deals with both the Xtensa-specific property sections and the Xtensa literal sections. The property section for a group needs to be made a member of that group, and there are a few places that needed updating the handle the property section names with the group suffixes. The literal sections are harder. The Xtensa "literal_prefix" directive that was used to control literal section names does not allow specifying a section in a group, and rather than extend it to be even more complicated, the patch changes the default behavior to "do the right thing". The literal_prefix directive still works as before, but if it is not specified, the assembler determines which literal section to use based on the section where a literal is defined. The details are in the updated documentation.

2006-08-24 Bob Wilson <bob.wilson@acm.org>

bfd/
	* elf32-xtensa.c (xtensa_get_property_section_name): Delete.
	(xtensa_get_property_section): New.
	(xtensa_read_table_entries): Use xtensa_get_property_section.
	(relax_property_section, xtensa_get_property_predef_flags): Handle
	group name suffixes in property section names.
	(match_section_group): New.

gas/
	* config/tc-xtensa.c (FINI_LITERAL_SECTION_NAME): Delete.
	(INIT_LITERAL_SECTION_NAME): Delete.
	(lit_state struct): Remove segment names, init_lit_seg, and
	fini_lit_seg.  Add lit_prefix and current_text_seg.
	(init_literal_head_h, init_literal_head): Delete.
	(fini_literal_head_h, fini_literal_head): Delete.
	(xtensa_begin_directive): Move argument parsing to
	xtensa_literal_prefix function.
	(xtensa_end_directive): Deallocate lit_prefix field of lit_state.
	(xtensa_literal_prefix): Parse the directive argument here and
	record it in the lit_prefix field.  Remove code to derive literal
	section names.
	(linkonce_len): New.
	(get_is_linkonce_section): Use linkonce_len.  Check for any
	".gnu.linkonce.*" section, not just text sections.
	(md_begin): Remove initialization of deleted lit_state fields.
	(xtensa_reorder_segments, xtensa_post_relax_hook): Remove references
	to init_literal_head and fini_literal_head.
	(xtensa_move_literals): Likewise.  Skip literals for .init and .fini
	when traversing literal_head list.
	(match_section_group): New.
	(cache_literal_section): Rewrite to determine the literal section
	name on the fly, create the section and return it.
	(xtensa_switch_to_literal_fragment): Adjust for cache_literal_section.
	(xtensa_switch_to_non_abs_literal_fragment): Likewise.
	(xtensa_create_property_segments, xtensa_create_xproperty_segments):
	Use xtensa_get_property_section from bfd.
	(retrieve_xtensa_section): Delete.
	* doc/c-xtensa.texi (Xtensa Options): Fix --text-section-literals
	description to refer to plural literal sections and add xref to
	the Literal Directive section.
	(Literal Directive): Describe new rules for deriving literal section
	names.  Add footnote for special case of .init/.fini with
	--text-section-literals.
	(Literal Prefix Directive): Replace old naming rules with xref to the
	Literal Directive section.

ld/
	* emulparams/elf32xtensa.sh (.xt.prop): Add .xt.prop.*.
	* scripttempl/elfxtensa.sc (.text): Add .literal.*.

Index: bfd/elf32-xtensa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-xtensa.c,v
retrieving revision 1.67
diff -u -p -r1.67 elf32-xtensa.c
--- bfd/elf32-xtensa.c	26 Jul 2006 12:32:27 -0000	1.67
+++ bfd/elf32-xtensa.c	24 Aug 2006 22:54:40 -0000
@@ -106,7 +106,7 @@ static bfd_boolean xtensa_is_property_se
 static bfd_boolean xtensa_is_littable_section (asection *);
 static int internal_reloc_compare (const void *, const void *);
 static int internal_reloc_matches (const void *, const void *);
-extern char *xtensa_get_property_section_name (asection *, const char *);
+extern asection *xtensa_get_property_section (asection *, const char *);
 static flagword xtensa_get_property_predef_flags (asection *);
 
 /* Other functions called directly by the linker.  */
@@ -571,7 +571,6 @@ xtensa_read_table_entries (bfd *abfd,
 			   bfd_boolean output_addr)
 {
   asection *table_section;
-  char *table_section_name;
   bfd_size_type table_size = 0;
   bfd_byte *table_data;
   property_table_entry *blocks;
@@ -590,9 +589,7 @@ xtensa_read_table_entries (bfd *abfd,
       return 0;
     }
 
-  table_section_name = xtensa_get_property_section_name (section, sec_name);
-  table_section = bfd_get_section_by_name (abfd, table_section_name);
-  free (table_section_name);
+  table_section = xtensa_get_property_section (section, sec_name);
   if (table_section)
     table_size = table_section->size;
 
@@ -8857,7 +8854,8 @@ relax_property_section (bfd *abfd,
     }
 
   is_full_prop_section =
-    ((strcmp (sec->name, XTENSA_PROP_SEC_NAME) == 0)
+    ((strncmp (sec->name, XTENSA_PROP_SEC_NAME,
+	       sizeof (XTENSA_PROP_SEC_NAME) - 1) == 0)
      || (strncmp (sec->name, ".gnu.linkonce.prop.",
 		  sizeof ".gnu.linkonce.prop." - 1) == 0));
 
@@ -9593,13 +9591,42 @@ internal_reloc_matches (const void *ap, 
 }
 
 
-char *
-xtensa_get_property_section_name (asection *sec, const char *base_name)
+/* Predicate function used to look up a section in a particular group.  */
+
+static bfd_boolean
+match_section_group (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
+{
+  const char *gname = inf;
+  const char *group_name = elf_group_name (sec);
+  
+  return (group_name == gname
+	  || (group_name != NULL
+	      && gname != NULL
+	      && strcmp (group_name, gname) == 0));
+}
+
+
+asection *
+xtensa_get_property_section (asection *sec, const char *base_name)
 {
-  if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0)
+  const char *suffix, *group_name;
+  char *prop_sec_name;
+  asection *prop_sec;
+
+  group_name = elf_group_name (sec);
+  if (group_name)
+    {
+      suffix = strrchr (sec->name, '.');
+      if (suffix == sec->name)
+	suffix = 0;
+      prop_sec_name = (char *) bfd_malloc (strlen (base_name) + 1
+					   + (suffix ? strlen (suffix) : 0));
+      strcpy (prop_sec_name, base_name);
+      if (suffix)
+	strcat (prop_sec_name, suffix);
+    }
+  else if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0)
     {
-      char *prop_sec_name;
-      const char *suffix;
       char *linkonce_kind = 0;
 
       if (strcmp (base_name, XTENSA_INSN_SEC_NAME) == 0) 
@@ -9622,18 +9649,39 @@ xtensa_get_property_section_name (asecti
       if (strncmp (suffix, "t.", 2) == 0 && linkonce_kind[1] == '.')
         suffix += 2;
       strcat (prop_sec_name + linkonce_len, suffix);
+    }
+  else
+    prop_sec_name = strdup (base_name);
+
+  /* Check if the section already exists.  */
+  prop_sec = bfd_get_section_by_name_if (sec->owner, prop_sec_name,
+					 match_section_group,
+					 (void *) group_name);
+  /* If not, create it.  */
+  if (! prop_sec)
+    {
+      flagword flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY);
+      flags |= (bfd_get_section_flags (sec->owner, sec)
+		& (SEC_LINK_ONCE | SEC_LINK_DUPLICATES));
+
+      prop_sec = bfd_make_section_anyway_with_flags
+	(sec->owner, strdup (prop_sec_name), flags);
+      if (! prop_sec)
+	return 0;
 
-      return prop_sec_name;
+      elf_group_name (prop_sec) = group_name;
     }
 
-  return strdup (base_name);
+  free (prop_sec_name);
+  return prop_sec;
 }
 
 
 flagword
 xtensa_get_property_predef_flags (asection *sec)
 {
-  if (strcmp (sec->name, XTENSA_INSN_SEC_NAME) == 0
+  if (strncmp (sec->name, XTENSA_INSN_SEC_NAME,
+	       sizeof (XTENSA_INSN_SEC_NAME) - 1) == 0
       || strncmp (sec->name, ".gnu.linkonce.x.",
 		  sizeof ".gnu.linkonce.x." - 1) == 0)
     return (XTENSA_PROP_INSN
Index: gas/config/tc-xtensa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-xtensa.c,v
retrieving revision 1.68
diff -u -p -r1.68 tc-xtensa.c
--- gas/config/tc-xtensa.c	7 Jun 2006 11:27:58 -0000	1.68
+++ gas/config/tc-xtensa.c	24 Aug 2006 22:54:46 -0000
@@ -95,33 +95,32 @@ static bfd_boolean past_xtensa_end = FAL
 
 #define LITERAL_SECTION_NAME		xtensa_section_rename (".literal")
 #define LIT4_SECTION_NAME		xtensa_section_rename (".lit4")
-#define FINI_SECTION_NAME		xtensa_section_rename (".fini")
 #define INIT_SECTION_NAME		xtensa_section_rename (".init")
-#define FINI_LITERAL_SECTION_NAME	xtensa_section_rename (".fini.literal")
-#define INIT_LITERAL_SECTION_NAME	xtensa_section_rename (".init.literal")
+#define FINI_SECTION_NAME		xtensa_section_rename (".fini")
 
 
 /* This type is used for the directive_stack to keep track of the
-   state of the literal collection pools.  */
+   state of the literal collection pools.  If lit_prefix is set, it is
+   used to determine the literal section names; otherwise, the literal
+   sections are determined based on the current text section.  The
+   lit_seg and lit4_seg fields cache these literal sections, with the
+   current_text_seg field used a tag to indicate whether the cached
+   values are valid.  */
 
 typedef struct lit_state_struct
 {
-  const char *lit_seg_name;
-  const char *lit4_seg_name;
-  const char *init_lit_seg_name;
-  const char *fini_lit_seg_name;
+  char *lit_prefix;
+  segT current_text_seg;
   segT lit_seg;
   segT lit4_seg;
-  segT init_lit_seg;
-  segT fini_lit_seg;
 } lit_state;
 
 static lit_state default_lit_sections;
 
 
-/* We keep lists of literal segments.  The seg_list type is the node
-   for such a list.  The *_literal_head locals are the heads of the
-   various lists.  All of these lists have a dummy node at the start.  */
+/* We keep a list of literal segments.  The seg_list type is the node
+   for this list.  The literal_head pointer is the head of the list,
+   with the literal_head_h dummy node at the start.  */
 
 typedef struct seg_list_struct
 {
@@ -131,10 +130,6 @@ typedef struct seg_list_struct
 
 static seg_list literal_head_h;
 static seg_list *literal_head = &literal_head_h;
-static seg_list init_literal_head_h;
-static seg_list *init_literal_head = &init_literal_head_h;
-static seg_list fini_literal_head_h;
-static seg_list *fini_literal_head = &fini_literal_head_h;
 
 
 /* Lists of symbols.  We keep a list of symbols that label the current
@@ -414,7 +409,7 @@ bfd_boolean directive_state[] =
 
 static void xtensa_begin_directive (int);
 static void xtensa_end_directive (int);
-static void xtensa_literal_prefix (char const *, int);
+static void xtensa_literal_prefix (void);
 static void xtensa_literal_position (int);
 static void xtensa_literal_pseudo (int);
 static void xtensa_frequency_pseudo (int);
@@ -463,12 +458,11 @@ static void xtensa_switch_to_literal_fra
 static void xtensa_switch_to_non_abs_literal_fragment (emit_state *);
 static void xtensa_switch_section_emit_state (emit_state *, segT, subsegT);
 static void xtensa_restore_emit_state (emit_state *);
-static void cache_literal_section
-  (seg_list *, const char *, segT *, bfd_boolean);
+static segT cache_literal_section (bfd_boolean);
 
 /* Import from elf32-xtensa.c in BFD library.  */
 
-extern char *xtensa_get_property_section_name (asection *, const char *);
+extern asection *xtensa_get_property_section (asection *, const char *);
 
 /* op_placement_info functions.  */
 
@@ -1173,7 +1167,6 @@ xtensa_begin_directive (int ignore ATTRI
   directiveE directive;
   bfd_boolean negated;
   emit_state *state;
-  int len;
   lit_state *ls;
 
   get_directive (&directive, &negated);
@@ -1220,20 +1213,10 @@ xtensa_begin_directive (int ignore ATTRI
       assert (ls);
 
       *ls = default_lit_sections;
-
       directive_push (directive_literal_prefix, negated, ls);
 
-      /* Parse the new prefix from the input_line_pointer.  */
-      SKIP_WHITESPACE ();
-      len = strspn (input_line_pointer,
-		    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-		    "abcdefghijklmnopqrstuvwxyz_/0123456789.$");
-
       /* Process the new prefix.  */
-      xtensa_literal_prefix (input_line_pointer, len);
-
-      /* Skip the name in the input line.  */
-      input_line_pointer += len;
+      xtensa_literal_prefix ();
       break;
 
     case directive_freeregs:
@@ -1353,10 +1336,10 @@ xtensa_end_directive (int ignore ATTRIBU
 	      /* Restore the default collection sections from saved state.  */
 	      s = (lit_state *) state;
 	      assert (s);
-
 	      default_lit_sections = *s;
 
-	      /* free the state storage */
+	      /* Free the state storage.  */
+	      free (s->lit_prefix);
 	      free (s);
 	      break;
 
@@ -1463,62 +1446,31 @@ xtensa_literal_pseudo (int ignored ATTRI
 
 
 static void
-xtensa_literal_prefix (char const *start, int len)
+xtensa_literal_prefix (void)
 {
-  char *name, *linkonce_suffix;
-  char *newname, *newname4;
-  size_t linkonce_len;
+  char *name;
+  int len;
+
+  /* Parse the new prefix from the input_line_pointer.  */
+  SKIP_WHITESPACE ();
+  len = strspn (input_line_pointer,
+		"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+		"abcdefghijklmnopqrstuvwxyz_/0123456789.$");
 
   /* Get a null-terminated copy of the name.  */
   name = xmalloc (len + 1);
   assert (name);
-
-  strncpy (name, start, len);
+  strncpy (name, input_line_pointer, len);
   name[len] = 0;
 
-  /* Allocate the sections (interesting note: the memory pointing to
-     the name is actually used for the name by the new section). */
-
-  newname = xmalloc (len + strlen (".literal") + 1);
-  newname4 = xmalloc (len + strlen (".lit4") + 1);
-
-  linkonce_len = sizeof (".gnu.linkonce.") - 1;
-  if (strncmp (name, ".gnu.linkonce.", linkonce_len) == 0
-      && (linkonce_suffix = strchr (name + linkonce_len, '.')) != 0)
-    {
-      strcpy (newname, ".gnu.linkonce.literal");
-      strcpy (newname4, ".gnu.linkonce.lit4");
-
-      strcat (newname, linkonce_suffix);
-      strcat (newname4, linkonce_suffix);
-    }
-  else
-    {
-      int suffix_pos = len;
-
-      /* If the section name ends with ".text", then replace that suffix
-	 instead of appending an additional suffix.  */
-      if (len >= 5 && strcmp (name + len - 5, ".text") == 0)
-	suffix_pos -= 5;
+  /* Skip the name in the input line.  */
+  input_line_pointer += len;
 
-      strcpy (newname, name);
-      strcpy (newname4, name);
-
-      strcpy (newname + suffix_pos, ".literal");
-      strcpy (newname4 + suffix_pos, ".lit4");
-    }
+  default_lit_sections.lit_prefix = name;
 
-  /* Note that cache_literal_section does not create a segment if
-     it already exists.  */
+  /* Clear cached literal sections, since the prefix has changed.  */
   default_lit_sections.lit_seg = NULL;
   default_lit_sections.lit4_seg = NULL;
-
-  /* Canonicalizing section names allows renaming literal
-     sections to occur correctly.  */
-  default_lit_sections.lit_seg_name = tc_canonicalize_symbol_name (newname);
-  default_lit_sections.lit4_seg_name = tc_canonicalize_symbol_name (newname4);
-
-  free (name);
 }
 
 
@@ -3921,7 +3873,9 @@ xg_expand_assembly_insn (IStack *istack,
 
 
 /* Return TRUE if the section flags are marked linkonce
-   or the name is .gnu.linkonce*.  */
+   or the name is .gnu.linkonce.*.  */
+
+static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
 
 static bfd_boolean
 get_is_linkonce_section (bfd *abfd ATTRIBUTE_UNUSED, segT sec)
@@ -3932,13 +3886,10 @@ get_is_linkonce_section (bfd *abfd ATTRI
   link_once_flags = (flags & SEC_LINK_ONCE);
 
   /* Flags might not be set yet.  */
-  if (!link_once_flags)
-    {
-      static size_t len = sizeof ".gnu.linkonce.t.";
+  if (!link_once_flags
+      && strncmp (segment_name (sec), ".gnu.linkonce.", linkonce_len) == 0)
+    link_once_flags = SEC_LINK_ONCE;
 
-      if (strncmp (segment_name (sec), ".gnu.linkonce.t.", len - 1) == 0)
-	link_once_flags = SEC_LINK_ONCE;
-    }
   return (link_once_flags != 0);
 }
 
@@ -4946,12 +4897,8 @@ md_begin (void)
 
   linkrelax = 1;
 
-  /* Set up the .literal, .fini.literal and .init.literal sections.  */
+  /* Set up the literal sections.  */
   memset (&default_lit_sections, 0, sizeof (default_lit_sections));
-  default_lit_sections.init_lit_seg_name = INIT_LITERAL_SECTION_NAME;
-  default_lit_sections.fini_lit_seg_name = FINI_LITERAL_SECTION_NAME;
-  default_lit_sections.lit_seg_name = LITERAL_SECTION_NAME;
-  default_lit_sections.lit4_seg_name = LIT4_SECTION_NAME;
 
   subseg_set (current_section, current_subsec);
 
@@ -9694,15 +9641,17 @@ xtensa_move_literals (void)
   sym_list *lit;
 
   mark_literal_frags (literal_head->next);
-  mark_literal_frags (init_literal_head->next);
-  mark_literal_frags (fini_literal_head->next);
 
   if (use_literal_section)
     return;
 
-  segment = literal_head->next;
-  while (segment)
+  for (segment = literal_head->next; segment; segment = segment->next)
     {
+      /* Keep the literals for .init and .fini in separate sections.  */
+      if (!strcmp (segment_name (segment->seg), INIT_SECTION_NAME)
+	  || !strcmp (segment_name (segment->seg), FINI_SECTION_NAME))
+	continue;
+
       frchain_from = seg_info (segment->seg)->frchainP;
       search_frag = frchain_from->frch_root;
       literal_pool = NULL;
@@ -9786,7 +9735,6 @@ xtensa_move_literals (void)
 	}
       frchain_from->fix_tail = NULL;
       xtensa_restore_emit_state (&state);
-      segment = segment->next;
     }
 
   /* Now fix up the SEGMENT value for all the literal symbols.  */
@@ -9867,8 +9815,6 @@ xtensa_reorder_segments (void)
   /* Now that we have the last section, push all the literal
      sections to the end.  */
   xtensa_reorder_seg_list (literal_head, last_sec);
-  xtensa_reorder_seg_list (init_literal_head, last_sec);
-  xtensa_reorder_seg_list (fini_literal_head, last_sec);
 
   /* Now perform the final error check.  */
   for (sec = stdoutput->sections; sec != NULL; sec = sec->next)
@@ -9886,10 +9832,8 @@ xtensa_switch_to_literal_fragment (emit_
 {
   if (directive_state[directive_absolute_literals])
     {
-      cache_literal_section (0, default_lit_sections.lit4_seg_name,
-			     &default_lit_sections.lit4_seg, FALSE);
-      xtensa_switch_section_emit_state (result,
-					default_lit_sections.lit4_seg, 0);
+      segT lit4_seg = cache_literal_section (TRUE);
+      xtensa_switch_section_emit_state (result, lit4_seg, 0);
     }
   else
     xtensa_switch_to_non_abs_literal_fragment (result);
@@ -9903,17 +9847,11 @@ xtensa_switch_to_literal_fragment (emit_
 static void
 xtensa_switch_to_non_abs_literal_fragment (emit_state *result)
 {
-  /* When we mark a literal pool location, we want to put a frag in
-     the literal pool that points to it.  But to do that, we want to
-     switch_to_literal_fragment.  But literal sections don't have
-     literal pools, so their location is always null, so we would
-     recurse forever.  This is kind of hacky, but it works.  */
-
   static bfd_boolean recursive = FALSE;
   fragS *pool_location = get_literal_pool_location (now_seg);
+  segT lit_seg;
   bfd_boolean is_init =
     (now_seg && !strcmp (segment_name (now_seg), INIT_SECTION_NAME));
-
   bfd_boolean is_fini =
     (now_seg && !strcmp (segment_name (now_seg), FINI_SECTION_NAME));
 
@@ -9923,39 +9861,20 @@ xtensa_switch_to_non_abs_literal_fragmen
       && !is_init && ! is_fini)
     {
       as_bad (_("literal pool location required for text-section-literals; specify with .literal_position"));
+
+      /* When we mark a literal pool location, we want to put a frag in
+	 the literal pool that points to it.  But to do that, we want to
+	 switch_to_literal_fragment.  But literal sections don't have
+	 literal pools, so their location is always null, so we would
+	 recurse forever.  This is kind of hacky, but it works.  */
+
       recursive = TRUE;
       xtensa_mark_literal_pool_location ();
       recursive = FALSE;
     }
 
-  /* Special case: If we are in the ".fini" or ".init" section, then
-     we will ALWAYS be generating to the ".fini.literal" and
-     ".init.literal" sections.  */
-
-  if (is_init)
-    {
-      cache_literal_section (init_literal_head,
-			     default_lit_sections.init_lit_seg_name,
-			     &default_lit_sections.init_lit_seg, TRUE);
-      xtensa_switch_section_emit_state (result,
-					default_lit_sections.init_lit_seg, 0);
-    }
-  else if (is_fini)
-    {
-      cache_literal_section (fini_literal_head,
-			     default_lit_sections.fini_lit_seg_name,
-			     &default_lit_sections.fini_lit_seg, TRUE);
-      xtensa_switch_section_emit_state (result,
-					default_lit_sections.fini_lit_seg, 0);
-    }
-  else
-    {
-      cache_literal_section (literal_head,
-			     default_lit_sections.lit_seg_name,
-			     &default_lit_sections.lit_seg, TRUE);
-      xtensa_switch_section_emit_state (result,
-					default_lit_sections.lit_seg, 0);
-    }
+  lit_seg = cache_literal_section (FALSE);
+  xtensa_switch_section_emit_state (result, lit_seg, 0);
 
   if (!use_literal_section
       && !is_init && !is_fini
@@ -9999,49 +9918,129 @@ xtensa_restore_emit_state (emit_state *s
 }
 
 
-/* Get a segment of a given name.  If the segment is already
-   present, return it; otherwise, create a new one.  */
+/* Predicate function used to look up a section in a particular group.  */
 
-static void
-cache_literal_section (seg_list *head,
-		       const char *name,
-		       segT *pseg,
-		       bfd_boolean is_code)
+static bfd_boolean
+match_section_group (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
 {
-  segT current_section = now_seg;
-  int current_subsec = now_subseg;
-  segT seg;
+  const char *gname = inf;
+  const char *group_name = elf_group_name (sec);
+  
+  return (group_name == gname
+	  || (group_name != NULL
+	      && gname != NULL
+	      && strcmp (group_name, gname) == 0));
+}
 
-  if (*pseg != 0)
-    return;
 
-  /* Check if the named section exists.  */
-  for (seg = stdoutput->sections; seg; seg = seg->next)
+/* Get the literal section to be used for the current text section.
+   The result may be cached in the default_lit_sections structure.  */
+
+static segT
+cache_literal_section (bfd_boolean use_abs_literals)
+{
+  const char *text_name, *group_name = 0;
+  char *base_name, *name, *suffix;
+  segT *pcached;
+  segT seg, current_section;
+  int current_subsec;
+  bfd_boolean linkonce = FALSE;
+
+  /* Save the current section/subsection.  */
+  current_section = now_seg;
+  current_subsec = now_subseg;
+
+  /* Clear the cached values if they are no longer valid.  */
+  if (now_seg != default_lit_sections.current_text_seg)
+    {
+      default_lit_sections.current_text_seg = now_seg;
+      default_lit_sections.lit_seg = NULL;
+      default_lit_sections.lit4_seg = NULL;
+    }
+
+  /* Check if the literal section is already cached.  */
+  if (use_abs_literals)
+    pcached = &default_lit_sections.lit4_seg;
+  else
+    pcached = &default_lit_sections.lit_seg;
+
+  if (*pcached)
+    return *pcached;
+  
+  text_name = default_lit_sections.lit_prefix;
+  if (! text_name || ! *text_name)
     {
-      if (!strcmp (segment_name (seg), name))
-	break;
+      text_name = segment_name (current_section);
+      group_name = elf_group_name (current_section);
+      linkonce = (current_section->flags & SEC_LINK_ONCE) != 0;
     }
 
-  if (!seg)
+  base_name = use_abs_literals ? ".lit4" : ".literal";
+  if (group_name)
+    {
+      name = xmalloc (strlen (base_name) + strlen (group_name) + 2);
+      sprintf (name, "%s.%s", base_name, group_name);
+    }
+  else if (strncmp (text_name, ".gnu.linkonce.", linkonce_len) == 0)
     {
-      /* Create a new literal section.  */
-      seg = subseg_new (name, (subsegT) 0);
-      if (head)
+      suffix = strchr (text_name + linkonce_len, '.');
+
+      name = xmalloc (linkonce_len + strlen (base_name) + 1
+		      + (suffix ? strlen (suffix) : 0));
+      strcpy (name, ".gnu.linkonce");
+      strcat (name, base_name);
+      if (suffix)
+	strcat (name, suffix);
+      linkonce = TRUE;
+    }
+  else
+    {
+      /* If the section name ends with ".text", then replace that suffix
+	 instead of appending an additional suffix.  */
+      size_t len = strlen (text_name);
+      if (len >= 5 && strcmp (text_name + len - 5, ".text") == 0)
+	len -= 5;
+
+      name = xmalloc (len + strlen (base_name) + 1);
+      strcpy (name, text_name);
+      strcpy (name + len, base_name);
+    }
+
+  /* Canonicalize section names to allow renaming literal sections.
+     The group name, if any, came from the current text section and
+     has already been canonicalized.  */
+  name = tc_canonicalize_symbol_name (name);
+
+  seg = bfd_get_section_by_name_if (stdoutput, name, match_section_group,
+				    (void *) group_name);
+  if (! seg)
+    {
+      flagword flags;
+
+      seg = subseg_force_new (name, 0);
+
+      if (! use_abs_literals)
 	{
-	  /* Add the newly created literal segment to the specified list.  */
+	  /* Add the newly created literal segment to the list.  */
 	  seg_list *n = (seg_list *) xmalloc (sizeof (seg_list));
 	  n->seg = seg;
-	  n->next = head->next;
-	  head->next = n;
+	  n->next = literal_head->next;
+	  literal_head->next = n;
 	}
-      bfd_set_section_flags (stdoutput, seg, SEC_HAS_CONTENTS |
-			     SEC_READONLY | SEC_ALLOC | SEC_LOAD
-			     | (is_code ? SEC_CODE : SEC_DATA));
+
+      flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC | SEC_LOAD
+	       | (linkonce ? (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD) : 0)
+	       | (use_abs_literals ? SEC_DATA : SEC_CODE));
+
+      elf_group_name (seg) = group_name;
+
+      bfd_set_section_flags (stdoutput, seg, flags);
       bfd_set_section_alignment (stdoutput, seg, 2);
     }
 
-  *pseg = seg;
+  *pcached = seg;
   subseg_set (current_section, current_subsec);
+  return seg;
 }
 
 
@@ -10060,7 +10059,6 @@ static void xtensa_create_property_segme
 static void xtensa_create_xproperty_segments
   (frag_flags_fn, const char *, xt_section_type);
 static segment_info_type *retrieve_segment_info (segT);
-static segT retrieve_xtensa_section (char *);
 static bfd_boolean section_has_property (segT, frag_predicate);
 static bfd_boolean section_has_xproperty (segT, frag_flags_fn);
 static void add_xt_block_frags
@@ -10078,8 +10076,6 @@ void
 xtensa_post_relax_hook (void)
 {
   xtensa_move_seg_list_to_beginning (literal_head);
-  xtensa_move_seg_list_to_beginning (init_literal_head);
-  xtensa_move_seg_list_to_beginning (fini_literal_head);
 
   xtensa_find_unmarked_state_frags ();
 
@@ -10135,9 +10131,8 @@ xtensa_create_property_segments (frag_pr
 
       if (section_has_property (sec, property_function))
 	{
-	  char *property_section_name =
-	    xtensa_get_property_section_name (sec, section_name_base);
-	  segT insn_sec = retrieve_xtensa_section (property_section_name);
+	  segT insn_sec = 
+	    xtensa_get_property_section (sec, section_name_base);
 	  segment_info_type *xt_seg_info = retrieve_segment_info (insn_sec);
 	  xtensa_block_info **xt_blocks =
 	    &xt_seg_info->tc_segment_info_data.blocks[sec_type];
@@ -10268,9 +10263,8 @@ xtensa_create_xproperty_segments (frag_f
 
       if (section_has_xproperty (sec, flag_fn))
 	{
-	  char *property_section_name =
-	    xtensa_get_property_section_name (sec, section_name_base);
-	  segT insn_sec = retrieve_xtensa_section (property_section_name);
+	  segT insn_sec =
+	    xtensa_get_property_section (sec, section_name_base);
 	  segment_info_type *xt_seg_info = retrieve_segment_info (insn_sec);
 	  xtensa_block_info **xt_blocks =
 	    &xt_seg_info->tc_segment_info_data.blocks[sec_type];
@@ -10414,29 +10408,6 @@ retrieve_segment_info (segT seg)
 }
 
 
-static segT
-retrieve_xtensa_section (char *sec_name)
-{
-  bfd *abfd = stdoutput;
-  flagword flags, out_flags, link_once_flags;
-  segT s;
-
-  flags = bfd_get_section_flags (abfd, now_seg);
-  link_once_flags = (flags & SEC_LINK_ONCE);
-  if (link_once_flags)
-    link_once_flags |= (flags & SEC_LINK_DUPLICATES);
-  out_flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY | link_once_flags);
-
-  s = bfd_make_section_old_way (abfd, sec_name);
-  if (s == NULL)
-    as_bad (_("could not create section %s"), sec_name);
-  if (!bfd_set_section_flags (abfd, s, out_flags))
-    as_bad (_("invalid flag combination on section %s"), sec_name);
-
-  return s;
-}
-
-
 static bfd_boolean
 section_has_property (segT sec, frag_predicate property_function)
 {
Index: gas/doc/c-xtensa.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-xtensa.texi,v
retrieving revision 1.8
diff -u -p -r1.8 c-xtensa.texi
--- gas/doc/c-xtensa.texi	24 Jul 2006 13:49:49 -0000	1.8
+++ gas/doc/c-xtensa.texi	24 Aug 2006 22:54:47 -0000
@@ -37,8 +37,8 @@ special options:
 @kindex --text-section-literals
 @kindex --no-text-section-literals
 Control the treatment of literal pools.  The default is
-@samp{--no-@-text-@-section-@-literals}, which places literals in a
-separate section in the output file.  This allows the literal pool to be
+@samp{--no-@-text-@-section-@-literals}, which places literals in
+separate sections in the output file.  This allows the literal pool to be
 placed in a data RAM/ROM.  With @samp{--text-@-section-@-literals}, the
 literals are interspersed in the text section in order to keep them as
 close as possible to their references.  This may be necessary for large
@@ -46,6 +46,7 @@ assembly files, where the literals would
 @code{L32R} instructions in the text section.  These options only affect
 literals referenced via PC-relative @code{L32R} instructions; literals
 for absolute mode @code{L32R} instructions are handled separately.
+@xref{Literal Directive, ,literal}.
 
 @item --absolute-literals | --no-absolute-literals
 @kindex --absolute-literals
@@ -617,13 +618,14 @@ can be used to load a pointer to the sym
 @code{ENTRY} and @code{L32R} instructions; instead, the assembler puts
 the data in a literal pool.
 
-Literal pools for absolute mode @code{L32R} instructions
-(@pxref{Absolute Literals Directive}) are placed in a separate
-@code{.lit4} section.  By default literal pools for PC-relative mode
-@code{L32R} instructions are placed in a separate @code{.literal}
-section; however, when using the @samp{--text-@-section-@-literals}
+Literal pools are placed by default in separate literal sections;
+however, when using the @samp{--text-@-section-@-literals}
 option (@pxref{Xtensa Options, ,Command Line Options}), the literal
-pools are placed in the current section.  These text section literal
+pools for PC-relative mode @code{L32R} instructions
+are placed in the current section.@footnote{Literals for the
+@code{.init} and @code{.fini} sections are always placed in separate
+sections, even when @samp{--text-@-section-@-literals} is enabled.}
+These text section literal
 pools are created automatically before @code{ENTRY} instructions and
 manually after @samp{.literal_position} directives (@pxref{Literal
 Position Directive, ,literal_position}).  If there are no preceding
@@ -631,6 +633,46 @@ Position Directive, ,literal_position}).
 must be used to place the text section literal pools; otherwise,
 @command{@value{AS}} will report an error.
 
+When literals are placed in separate sections, the literal section names
+are derived from the names of the sections where the literals are
+defined.  The base literal section names are @code{.literal} for
+PC-relative mode @code{L32R} instructions and @code{.lit4} for absolute
+mode @code{L32R} instructions (@pxref{Absolute Literals Directive,
+,absolute-literals}).  These base names are used for literals defined in
+the default @code{.text} section.  For literals defined in other
+sections or within the scope of a @code{literal_prefix} directive
+(@pxref{Literal Prefix Directive, ,literal_prefix}), the following rules
+determine the literal section name:
+
+@enumerate
+@item
+If the current section is a member of a section group, the literal
+section name includes the group name as a suffix to the base
+@code{.literal} or @code{.lit4} name, with a period to separate the base
+name and group name.  The literal section is also made a member of the
+group.
+
+@item
+If the current section name (or @code{literal_prefix} value) begins with
+``@code{.gnu.linkonce.@var{kind}.}'', the literal section name is formed
+by replacing ``@code{.@var{kind}}'' with the base @code{.literal} or
+@code{.lit4} name.  For example, for literals defined in a section named
+@code{.gnu.linkonce.t.func}, the literal section will be
+@code{.gnu.linkonce.literal.func} or @code{.gnu.linkonce.lit4.func}.
+
+@item
+If the current section name (or @code{literal_prefix} value) ends with
+@code{.text}, the literal section name is formed by replacing that
+suffix with the base @code{.literal} or @code{.lit4} name.  For example,
+for literals defined in a section named @code{.iram0.text}, the literal
+section will be @code{.iram0.literal} or @code{.iram0.lit4}.
+
+@item
+If none of the preceding conditions apply, the literal section name is
+formed by adding the base @code{.literal} or @code{.lit4} name as a
+suffix to the current section name (or @code{literal_prefix} value).
+@end enumerate
+
 @node Literal Position Directive
 @subsection literal_position
 @cindex @code{literal_position} directive
@@ -679,45 +721,24 @@ continue:
 @subsection literal_prefix
 @cindex @code{literal_prefix} directive
 
-The @code{literal_prefix} directive allows you to specify different
-sections to hold literals from different portions of an assembly file.
-With this directive, a single assembly file can be used to generate code
-into multiple sections, including literals generated by the assembler.
+The @code{literal_prefix} directive allows you to override the default
+literal section names, which are derived from the names of the sections
+where the literals are defined.
 
 @smallexample
     .begin literal_prefix [@var{name}]
     .end literal_prefix
 @end smallexample
 
-By default the assembler places literal pools in sections separate from
-the instructions, using the default literal section names of
-@code{.literal} for PC-relative mode @code{L32R} instructions and
-@code{.lit4} for absolute mode @code{L32R} instructions (@pxref{Absolute
-Literals Directive}).  The @code{literal_prefix} directive causes
-different literal sections to be used for the code inside the delimited
-region.  The new literal sections are determined by including @var{name}
-as a prefix to the default literal section names.  If the @var{name}
+For literals defined within the delimited region, the literal section
+names are derived from the @var{name} argument instead of the name of
+the current section.  The rules used to derive the literal section names
+do not change.  @xref{Literal Directive, ,literal}.  If the @var{name}
 argument is omitted, the literal sections revert to the defaults.  This
 directive has no effect when using the
 @samp{--text-@-section-@-literals} option (@pxref{Xtensa Options,
 ,Command Line Options}).
 
-Except for two special cases, the assembler determines the new literal
-sections by simply prepending @var{name} to the default section names,
-resulting in @code{@var{name}.literal} and @code{@var{name}.lit4}
-sections.  The @code{literal_prefix} directive is often used with the
-name of the current text section as the prefix argument.  To facilitate
-this usage, the assembler uses special case rules when it recognizes
-@var{name} as a text section name.  First, if @var{name} ends with
-@code{.text}, that suffix is not included in the literal section name.
-For example, if @var{name} is @code{.iram0.text}, then the literal
-sections will be @code{.iram0.literal} and @code{.iram0.lit4}.  Second,
-if @var{name} begins with @code{.gnu.linkonce.t.}, then the literal
-section names are formed by replacing the @code{.t} substring with
-@code{.literal} and @code{.lit4}.  For example, if @var{name} is
-@code{.gnu.linkonce.t.func}, the literal sections will be
-@code{.gnu.linkonce.literal.func} and @code{.gnu.linkonce.lit4.func}.
-
 @node Absolute Literals Directive
 @subsection absolute-literals
 @cindex @code{absolute-literals} directive
Index: ld/emulparams/elf32xtensa.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/elf32xtensa.sh,v
retrieving revision 1.5
diff -u -p -r1.5 elf32xtensa.sh
--- ld/emulparams/elf32xtensa.sh	12 May 2005 00:31:22 -0000	1.5
+++ ld/emulparams/elf32xtensa.sh	24 Aug 2006 22:54:47 -0000
@@ -31,5 +31,5 @@ OTHER_READWRITE_SECTIONS="
 OTHER_SECTIONS="
   .xt.lit         0 : { *(.xt.lit${RELOCATING+ .xt.lit.* .gnu.linkonce.p.*}) }
   .xt.insn        0 : { *(.xt.insn${RELOCATING+ .gnu.linkonce.x.*}) }
-  .xt.prop        0 : { *(.xt.prop${RELOCATING+ .gnu.linkonce.prop.*}) }
+  .xt.prop        0 : { *(.xt.prop${RELOCATING+ .xt.prop.* .gnu.linkonce.prop.*}) }
 "
Index: ld/scripttempl/elfxtensa.sc
===================================================================
RCS file: /cvs/src/src/ld/scripttempl/elfxtensa.sc,v
retrieving revision 1.8
diff -u -p -r1.8 elfxtensa.sc
--- ld/scripttempl/elfxtensa.sc	11 Dec 2005 00:49:19 -0000	1.8
+++ ld/scripttempl/elfxtensa.sc	24 Aug 2006 22:54:47 -0000
@@ -309,7 +309,7 @@ cat <<EOF
     ${RELOCATING+${INIT_END}}
 
     ${RELOCATING+${TEXT_START_SYMBOLS}}
-    *(.literal .text .stub${RELOCATING+ .text.* .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*})
+    *(.literal .text .stub${RELOCATING+ .literal.* .text.* .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*})
     KEEP (*(.text.*personality*))
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)

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