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]

Match archive:file in linker script filespecs


This extends the linker script input section file specification to
match files within archives.  I've chosen to enable this only for SPU,
where we need the feature to conveniently specify sections for
overlays.  (For instance, libgfortran contains read.o as does
newlib, and we might have read.o on the command line.)  If people
think this is a good idea the feature can be enabled on all targets,
and possibly for other filespecs such as those in EXCLUDE_FILE.

"archive:file" matches "file" within "archive"
"archive:"     matches the whole "archive"
":file"        matches "file" but not one in an archive

Either one or both of "archive" and "file" can contain shell wildcards.

include/
	* bfdlink.h (struct bfd_link_info): Add "path_separator".
bfd/
	* elf32-spu.c (spu_elf_auto_overlay): Relax requirement that
	file names be unique.  Specify archive:path in overlay script.
ld/
	* ldlang.c (name_match): New function.
	(unique_section_p, walk_wild_consider_section): Use it here.
	(walk_wild_section_general): And here.
	(archive_path): New function.
	(walk_wild): Match archive:path filespecs.
	(open_input_bfds): Don't load archive:path files.
	* emultempl/spuelf.em (choose_target): Set path_separator.

This one is unrelated but didn't seem worth a separate email.

	* emulparams/elf32_spu.sh: Add ._ea.* sections to ._ea output.

Index: include/bfdlink.h
===================================================================
RCS file: /cvs/src/src/include/bfdlink.h,v
retrieving revision 1.71
diff -u -p -r1.71 bfdlink.h
--- include/bfdlink.h	15 Feb 2008 03:35:51 -0000	1.71
+++ include/bfdlink.h	6 Jun 2008 01:53:15 -0000
@@ -372,6 +372,9 @@ struct bfd_link_info
      wrap_hash.  Used by PowerPC Linux for 'dot' symbols.  */
   char wrap_char;
 
+  /* Separator between archive and filename in linker script filespecs.  */
+  char path_separator;
+
   /* Function callbacks.  */
   const struct bfd_link_callbacks *callbacks;
 
Index: bfd/elf32-spu.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-spu.c,v
retrieving revision 1.43
diff -u -p -r1.43 elf32-spu.c
--- bfd/elf32-spu.c	4 Jun 2008 07:07:19 -0000	1.43
+++ bfd/elf32-spu.c	6 Jun 2008 02:09:39 -0000
@@ -3544,37 +3544,20 @@ spu_elf_auto_overlay (struct bfd_link_in
       for (i = 1; i < bfd_count; ++i)
 	if (strcmp (bfd_arr[i - 1]->filename, bfd_arr[i]->filename) == 0)
 	  {
-	    if (bfd_arr[i - 1]->my_archive && bfd_arr[i]->my_archive)
+	    if (bfd_arr[i - 1]->my_archive == bfd_arr[i]->my_archive)
 	      {
-		if (bfd_arr[i - 1]->my_archive == bfd_arr[i]->my_archive)
+		if (bfd_arr[i - 1]->my_archive && bfd_arr[i]->my_archive)
 		  info->callbacks->einfo (_("%s duplicated in %s\n"),
-					  bfd_arr[i - 1]->filename,
-					  bfd_arr[i - 1]->my_archive->filename);
-		else
-		  info->callbacks->einfo (_("%s in both %s and %s\n"),
-					  bfd_arr[i - 1]->filename,
-					  bfd_arr[i - 1]->my_archive->filename,
+					  bfd_arr[i]->filename,
 					  bfd_arr[i]->my_archive->filename);
+		else
+		  info->callbacks->einfo (_("%s duplicated\n"),
+					  bfd_arr[i]->filename);
+		ok = FALSE;
 	      }
-	    else if (bfd_arr[i - 1]->my_archive)
-	      info->callbacks->einfo (_("%s in %s and as an object\n"),
-				      bfd_arr[i - 1]->filename,
-				      bfd_arr[i - 1]->my_archive->filename);
-	    else if (bfd_arr[i]->my_archive)
-	      info->callbacks->einfo (_("%s in %s and as an object\n"),
-				      bfd_arr[i]->filename,
-				      bfd_arr[i]->my_archive->filename);
-	    else
-	      info->callbacks->einfo (_("%s duplicated\n"),
-				      bfd_arr[i]->filename);
-	    ok = FALSE;
 	  }
       if (!ok)
 	{
-	  /* FIXME: modify plain object files from foo.o to ./foo.o
-	     and emit EXCLUDE_FILE to handle the duplicates in
-	     archives.  There is a pathological case we can't handle:
-	     We may have duplicate file names within a single archive.  */
 	  info->callbacks->einfo (_("sorry, no support for duplicate "
 				    "object files in auto-overlay script\n"));
 	  bfd_set_error (bfd_error_bad_value);
@@ -3750,9 +3733,11 @@ spu_elf_auto_overlay (struct bfd_link_in
 	{
 	  asection *sec = ovly_sections[2 * j];
 
-	  if (fprintf (script, "   [%c]%s (%s)\n",
-		       sec->owner->filename[0],
-		       sec->owner->filename + 1,
+	  if (fprintf (script, "   %s%c%s (%s)\n",
+		       (sec->owner->my_archive != NULL
+			? sec->owner->my_archive->filename : ""),
+		       info->path_separator,
+		       sec->owner->filename,
 		       sec->name) <= 0)
 	    goto file_err;
 	  if (sec->segment_mark)
@@ -3762,9 +3747,11 @@ spu_elf_auto_overlay (struct bfd_link_in
 		{
 		  struct function_info *call_fun = call->fun;
 		  sec = call_fun->sec;
-		  if (fprintf (script, "   [%c]%s (%s)\n",
-			       sec->owner->filename[0],
-			       sec->owner->filename + 1,
+		  if (fprintf (script, "   %s%c%s (%s)\n",
+			       (sec->owner->my_archive != NULL
+				? sec->owner->my_archive->filename : ""),
+			       info->path_separator,
+			       sec->owner->filename,
 			       sec->name) <= 0)
 		    goto file_err;
 		  for (call = call_fun->call_list; call; call = call->next)
@@ -3777,10 +3764,13 @@ spu_elf_auto_overlay (struct bfd_link_in
       for (j = base; j < i; j++)
 	{
 	  asection *sec = ovly_sections[2 * j + 1];
-	  if (sec != NULL && fprintf (script, "   [%c]%s (%s)\n",
-				      sec->owner->filename[0],
-				      sec->owner->filename + 1,
-				      sec->name) <= 0)
+	  if (sec != NULL
+	      && fprintf (script, "   %s%c%s (%s)\n",
+			  (sec->owner->my_archive != NULL
+			   ? sec->owner->my_archive->filename : ""),
+			  info->path_separator,
+			  sec->owner->filename,
+			  sec->name) <= 0)
 	    goto file_err;
 
 	  sec = ovly_sections[2 * j];
@@ -3791,10 +3781,13 @@ spu_elf_auto_overlay (struct bfd_link_in
 		{
 		  struct function_info *call_fun = call->fun;
 		  sec = call_fun->rodata;
-		  if (sec != NULL && fprintf (script, "   [%c]%s (%s)\n",
-					      sec->owner->filename[0],
-					      sec->owner->filename + 1,
-					      sec->name) <= 0)
+		  if (sec != NULL
+		      && fprintf (script, "   %s%c%s (%s)\n",
+				  (sec->owner->my_archive != NULL
+				   ? sec->owner->my_archive->filename : ""),
+				  info->path_separator,
+				  sec->owner->filename,
+				  sec->name) <= 0)
 		    goto file_err;
 		  for (call = call_fun->call_list; call; call = call->next)
 		    if (call->is_pasted)
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.286
diff -u -p -r1.286 ldlang.c
--- ld/ldlang.c	31 May 2008 16:35:56 -0000	1.286
+++ ld/ldlang.c	6 Jun 2008 01:53:19 -0000
@@ -134,6 +134,38 @@ stat_alloc (size_t size)
   return obstack_alloc (&stat_obstack, size);
 }
 
+static int
+name_match (const char *pattern, const char *name)
+{
+  if (wildcardp (pattern))
+    return fnmatch (pattern, name, 0);
+  return strcmp (pattern, name);
+}
+
+/* If PATTERN is of the form archive:file, return a pointer to the
+   separator.  If not, return NULL.  */
+
+static char *
+archive_path (const char *pattern)
+{
+  char *p = NULL;
+
+  if (link_info.path_separator == 0)
+    return p;
+
+  p = strchr (pattern, link_info.path_separator);
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+  if (p == NULL || link_info.path_separator != ':')
+    return p;
+
+  /* Assume a match on the second char is part of drive specifier,
+     as in "c:\silly.dos".  */
+  if (p == pattern + 1)
+    p = strchr (p + 1, link_info.path_separator);
+#endif
+  return p;
+}
+
 bfd_boolean
 unique_section_p (const asection *sec)
 {
@@ -147,12 +179,8 @@ unique_section_p (const asection *sec)
 
   secnam = sec->name;
   for (unam = unique_section_list; unam; unam = unam->next)
-    if (wildcardp (unam->name)
-	? fnmatch (unam->name, secnam, 0) == 0
-	: strcmp (unam->name, secnam) == 0)
-      {
-	return TRUE;
-      }
+    if (name_match (unam->name, secnam) == 0)
+      return TRUE;
 
   return FALSE;
 }
@@ -175,17 +203,12 @@ walk_wild_consider_section (lang_wild_st
   bfd_boolean skip = FALSE;
   struct name_list *list_tmp;
 
-  /* Don't process sections from files which were
-     excluded.  */
+  /* Don't process sections from files which were excluded.  */
   for (list_tmp = sec->spec.exclude_name_list;
        list_tmp;
        list_tmp = list_tmp->next)
     {
-      bfd_boolean is_wildcard = wildcardp (list_tmp->name);
-      if (is_wildcard)
-	skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
-      else
-	skip = strcmp (list_tmp->name, file->filename) == 0;
+      skip = name_match (list_tmp->name, file->filename) == 0;
 
       /* If this file is part of an archive, and the archive is
 	 excluded, exclude this file.  */
@@ -193,13 +216,8 @@ walk_wild_consider_section (lang_wild_st
 	  && file->the_bfd->my_archive != NULL
 	  && file->the_bfd->my_archive->filename != NULL)
 	{
-	  if (is_wildcard)
-	    skip = fnmatch (list_tmp->name,
-			    file->the_bfd->my_archive->filename,
-			    0) == 0;
-	  else
-	    skip = strcmp (list_tmp->name,
-			   file->the_bfd->my_archive->filename) == 0;
+	  skip = name_match (list_tmp->name,
+			     file->the_bfd->my_archive->filename) == 0;
 	}
 
       if (skip)
@@ -236,10 +254,7 @@ walk_wild_section_general (lang_wild_sta
 	    {
 	      const char *sname = bfd_get_section_name (file->the_bfd, s);
 
-	      if (wildcardp (sec->spec.name))
-		skip = fnmatch (sec->spec.name, sname, 0) != 0;
-	      else
-		skip = strcmp (sec->spec.name, sname) != 0;
+	      skip = name_match (sec->spec.name, sname) != 0;
 	    }
 
 	  if (!skip)
@@ -780,6 +795,7 @@ static void
 walk_wild (lang_wild_statement_type *s, callback_t callback, void *data)
 {
   const char *file_spec = s->filename;
+  char *p;
 
   if (file_spec == NULL)
     {
@@ -789,6 +805,29 @@ walk_wild (lang_wild_statement_type *s, 
 	  walk_wild_file (s, f, callback, data);
 	}
     }
+  else if ((p = archive_path (file_spec)) != NULL)
+    {
+      LANG_FOR_EACH_INPUT_STATEMENT (f)
+	{
+	  if ((*(p + 1) == 0
+	       || name_match (p + 1, f->filename) == 0)
+	      && ((p != file_spec)
+		  == (f->the_bfd != NULL && f->the_bfd->my_archive != NULL)))
+	    {
+	      bfd_boolean skip = FALSE;
+
+	      if (p != file_spec)
+		{
+		  const char *aname = f->the_bfd->my_archive->filename;
+		  *p = 0;
+		  skip = name_match (file_spec, aname) != 0;
+		  *p = link_info.path_separator;
+		}
+	      if (!skip)
+		walk_wild_file (s, f, callback, data);
+	    }
+	}
+    }
   else if (wildcardp (file_spec))
     {
       LANG_FOR_EACH_INPUT_STATEMENT (f)
@@ -2931,7 +2970,8 @@ open_input_bfds (lang_statement_union_ty
 	case lang_wild_statement_enum:
 	  /* Maybe we should load the file's symbols.  */
 	  if (s->wild_statement.filename
-	      && ! wildcardp (s->wild_statement.filename))
+	      && !wildcardp (s->wild_statement.filename)
+	      && !archive_path (s->wild_statement.filename))
 	    lookup_name (s->wild_statement.filename);
 	  open_input_bfds (s->wild_statement.children.head, force);
 	  break;
Index: ld/emulparams/elf32_spu.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/elf32_spu.sh,v
retrieving revision 1.4
diff -u -p -r1.4 elf32_spu.sh
--- ld/emulparams/elf32_spu.sh	7 May 2008 14:46:44 -0000	1.4
+++ ld/emulparams/elf32_spu.sh	6 Jun 2008 01:53:19 -0000
@@ -18,4 +18,4 @@ MAXPAGESIZE=0x80
 DATA_ADDR="ALIGN(${MAXPAGESIZE})"
 OTHER_BSS_SECTIONS=".toe ALIGN(128) : { *(.toe) } = 0"
 OTHER_SECTIONS=".note.spu_name 0 : { KEEP(*(.note.spu_name)) }
-  ._ea 0 : { KEEP(*(._ea)) }"
+  ._ea 0 : { KEEP(*(._ea)) KEEP(*(._ea.*)) }"
Index: ld/emultempl/spuelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/spuelf.em,v
retrieving revision 1.20
diff -u -p -r1.20 spuelf.em
--- ld/emultempl/spuelf.em	4 Jun 2008 07:08:01 -0000	1.20
+++ ld/emultempl/spuelf.em	6 Jun 2008 01:53:22 -0000
@@ -350,6 +350,7 @@ gld${EMULATION_NAME}_finish (void)
 static char *
 gld${EMULATION_NAME}_choose_target (int argc, char *argv[])
 {
+  link_info.path_separator = ':';
   my_argc = argc;
   my_argv = argv;
   return ldemul_default_target (argc, argv);

-- 
Alan Modra
Australia Development Lab, IBM


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