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]

Extend "ld --unique" functionality.


Hi,
  This patch allows one to provide an input section name (or wildcard) as
a parameter to --unique.  Matching input sections will not be combined
according to the normal rules given by the default linker script; Instead
each one is placed into a separate output section.
  This is useful with "ld -r" for architectures such as HPPA which have a
limited branch range, where combining .text sections will likely result in
an output section that is too large to reach long branch stubs.  gcc's
-ffunction-sections isn't an ideal solution for this problem - see
http://sources.redhat.com/ml/libc-alpha/2000-08/msg00154.html for why.

ld/ChangeLog
	* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Don't
	rummage through the script for sections on the unique list.
	Correct length of strncmp for ".note".
	(gld${EMULATION_NAME}_check_needed): Rearrange function.

	* ldlang.c (unique_section_list): New var.
	(unique_section_p): New function.
	(walk_wild_section): Don't match sections on unique_section_list.
	(lang_add_unique): New function.
	Correct spelling of relocatable.

	* ldlang.h (struct unique_sections): Declare.
	(unique_section_list): Declare.
	(unique_section_p): Declare.
	(lang_add_unique): Declare.

	* lexsup.c (ld_options): Allow --unique to take an optional arg.
	(parse_args [OPTION_UNIQUE]): Call lang_add_unique.

	* ld.texinfo (--unique): Update.

Alan Modra
-- 
Linuxcare.  Support for the Revolution.

Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.32
diff -u -p -r1.32 ld.texinfo
--- ld.texinfo	2001/01/07 15:12:04	1.32
+++ ld.texinfo	2001/01/14 03:44:08
@@ -695,13 +695,15 @@ with @samp{-Ur}; once the constructor ta
 be added to.  Use @samp{-Ur} only for the last partial link, and
 @samp{-r} for the others.
 
-@kindex --unique
-@item --unique
-Creates a separate output section for every orphan input section.  This
-option prevents the normal merging of orphan input sections with the same
-name.  An orphan section is one not specifically mentioned in a linker
-script, so this option along with a custom linker script allows any
-selection of input sections to be merged while others are kept separate.
+@kindex --unique[=@var{SECTION}]
+@item --unique[=@var{SECTION}]
+Creates a separate output section for every input section matching
+@var{SECTION}, or if the optional wildcard @var{SECTION} argument is
+missing, for every orphan input section.  An orphan section is one not
+specifically mentioned in a linker script.  You may use this option
+multiple times on the command line;  It prevents the normal merging of
+input sections with the same name, overriding output section assignments
+in a linker script.
 
 @kindex -v
 @kindex -V
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.36
diff -u -p -r1.36 ldlang.c
--- ldlang.c	2000/12/13 18:28:52	1.36
+++ ldlang.c	2001/01/14 03:44:20
@@ -1,5 +1,5 @@
 /* Linker command language support.
-   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001
    Free Software Foundation, Inc.
 
 This file is part of GLD, the Gnu Linker.
@@ -186,6 +186,7 @@ boolean had_output_filename = false;
 boolean lang_float_flag = false;
 boolean delete_output_file_on_failure = false;
 struct lang_nocrossrefs *nocrossref_list;
+struct unique_sections *unique_section_list;
 
 etree_type *base; /* Relocation base - or null */
 
@@ -211,6 +212,23 @@ stat_alloc (size)
   return obstack_alloc (&stat_obstack, size);
 }
 
+boolean
+unique_section_p (secnam)
+     const char *secnam;
+{
+  struct unique_sections *unam;
+
+  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;
+      }
+
+  return false;
+}
+
 /* Generic traversal routines for finding matching sections.  */
 
 static void
@@ -242,31 +260,26 @@ walk_wild_section (ptr, section, file, c
   if (file->just_syms_flag == false)
     {
       register asection *s;
-      boolean wildcard;
+      boolean wildcard = false;
 
-      if (section == NULL)
-	wildcard = false;
-      else
+      if (section != NULL)
 	wildcard = wildcardp (section);
 
       for (s = file->the_bfd->sections; s != NULL; s = s->next)
 	{
 	  boolean match;
+	  const char *sname = bfd_get_section_name (file->the_bfd, s);
 
 	  if (section == NULL)
 	    match = true;
+	  else if (wildcard)
+	    match = fnmatch (section, sname, 0) == 0 ? true : false;
 	  else
-	    {
-	      const char *name;
+	    match = strcmp (section, sname) == 0 ? true : false;
 
-	      name = bfd_get_section_name (file->the_bfd, s);
-	      if (wildcard)
-		match = fnmatch (section, name, 0) == 0 ? true : false;
-	      else
-		match = strcmp (section, name) == 0 ? true : false;
-	    }
-
-	  if (match)
+	  /* If this is a wild-card output section statement, exclude
+	     sections that match UNIQUE_SECTION_LIST.  */
+	  if (match && (data == NULL || !unique_section_p (sname)))
 	    (*callback) (ptr, s, file, data);
 	}
     }
@@ -925,20 +938,20 @@ section_already_linked (abfd, sec, data)
   if ((flags & SEC_LINK_ONCE) == 0)
     return;
 
-  /* FIXME: When doing a relocateable link, we may have trouble
+  /* FIXME: When doing a relocatable link, we may have trouble
      copying relocations in other sections that refer to local symbols
      in the section being discarded.  Those relocations will have to
      be converted somehow; as of this writing I'm not sure that any of
      the backends handle that correctly.
 
      It is tempting to instead not discard link once sections when
-     doing a relocateable link (technically, they should be discarded
+     doing a relocatable link (technically, they should be discarded
      whenever we are building constructors).  However, that fails,
      because the linker winds up combining all the link once sections
      into a single large link once section, which defeats the purpose
      of having link once sections in the first place.
 
-     Also, not merging link once sections in a relocateable link
+     Also, not merging link once sections in a relocatable link
      causes trouble for MIPS ELF, which relies in link once semantics
      to handle the .reginfo section correctly.  */
 
@@ -5043,4 +5056,20 @@ lang_do_version_exports_section ()
   lreg = lang_new_vers_regex (NULL, "*", NULL);
   lang_register_vers_node (command_line.version_exports_section,
 			   lang_new_vers_node (greg, lreg), NULL);
+}
+
+void
+lang_add_unique (name)
+     const char *name;
+{
+  struct unique_sections *ent;
+
+  for (ent = unique_section_list; ent; ent = ent->next)
+    if (strcmp (ent->name, name) == 0)
+      return;
+
+  ent = (struct unique_sections *) xmalloc (sizeof *ent);
+  ent->name = xstrdup (name);
+  ent->next = unique_section_list;
+  unique_section_list = ent;
 }
Index: ld/ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.8
diff -u -p -r1.8 ldlang.h
--- ldlang.h	2000/10/09 15:09:17	1.8
+++ ldlang.h	2001/01/14 03:44:22
@@ -1,5 +1,5 @@
 /* ldlang.h - linker command language support
-   Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+   Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001
    Free Software Foundation, Inc.
 
    This file is part of GLD, the Gnu Linker.
@@ -340,6 +340,16 @@ struct lang_nocrossrefs {
 
 extern struct lang_nocrossrefs *nocrossref_list;
 
+/* This structure is used to hold a list of input section names which
+   will not match an output section in the linker script.  */
+
+struct unique_sections {
+  struct unique_sections *next;
+  const char *name;
+};
+
+extern struct unique_sections *unique_section_list;
+
 extern lang_output_section_statement_type *abs_output_section;
 extern lang_statement_list_type lang_output_section_statement;
 extern boolean lang_has_input_file;
@@ -462,5 +472,7 @@ extern struct bfd_elf_version_deps *lang
 extern void lang_register_vers_node
   PARAMS ((const char *, struct bfd_elf_version_tree *,
 	   struct bfd_elf_version_deps *));
+boolean unique_section_p PARAMS ((const char *));
+extern void lang_add_unique PARAMS ((const char *));
 
 #endif
Index: ld/lexsup.c
===================================================================
RCS file: /cvs/src/src/ld/lexsup.c,v
retrieving revision 1.28
diff -u -p -r1.28 lexsup.c
--- lexsup.c	2001/01/13 19:44:40	1.28
+++ lexsup.c	2001/01/14 03:44:26
@@ -236,8 +236,8 @@ static const struct ld_option ld_options
       'T', N_("FILE"), N_("Read linker script"), TWO_DASHES },
   { {"undefined", required_argument, NULL, 'u'},
       'u', N_("SYMBOL"), N_("Start with undefined reference to SYMBOL"), TWO_DASHES },
-  { {"unique", no_argument, NULL, OPTION_UNIQUE},
-      '\0', NULL, N_("Don't merge orphan sections with the same name"), TWO_DASHES },
+  { {"unique", optional_argument, NULL, OPTION_UNIQUE},
+      '\0', N_("[=SECTION]"), N_("Don't merge input [SECTION | orphan] sections"), TWO_DASHES },
   { {"Ur", no_argument, NULL, OPTION_UR},
       '\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH },
   { {"version", no_argument, NULL, OPTION_VERSION},
@@ -965,7 +965,10 @@ parse_args (argc, argv)
 	  ldlang_add_undef (optarg);
 	  break;
 	case OPTION_UNIQUE:
-	  config.unique_orphan_sections = true;
+	  if (optarg != NULL)
+	    lang_add_unique (optarg);
+	  else
+	    config.unique_orphan_sections = true;
 	  break;
 	case OPTION_VERBOSE:
 	  ldversion (1);
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.39
diff -u -p -r1.39 elf32.em
--- elf32.em	2001/01/08 05:25:58	1.39
+++ elf32.em	2001/01/14 03:44:30
@@ -7,7 +7,7 @@ cat >e${EMULATION_NAME}.c <<EOF
 /* This file is is generated by a shell script.  DO NOT EDIT! */
 
 /* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
-   Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 99, 2000
+   Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 99, 2000, 2001
    Free Software Foundation, Inc.
    Written by Steve Chamberlain <sac@cygnus.com>
    ELF support by Ian Lance Taylor <ian@cygnus.com>
@@ -527,11 +527,26 @@ gld${EMULATION_NAME}_check_needed (s)
   if (global_found)
     return;
 
-  if (s->filename != NULL
-      && strcmp (s->filename, global_needed->name) == 0)
+  if (s->filename != NULL)
     {
-      global_found = true;
-      return;
+      const char *f;
+
+      if (strcmp (s->filename, global_needed->name) == 0)
+	{
+	  global_found = true;
+	  return;
+	}
+
+      if (s->search_dirs_flag)
+	{
+	  f = strrchr (s->filename, '/');
+	  if (f != NULL
+	      && strcmp (f + 1, global_needed->name) == 0)
+	    {
+	      global_found = true;
+	      return;
+	    }
+	}
     }
 
   if (s->the_bfd != NULL)
@@ -546,21 +561,6 @@ gld${EMULATION_NAME}_check_needed (s)
 	  return;
 	}
     }
-	  
-  if (s->search_dirs_flag
-      && s->filename != NULL
-      && strchr (global_needed->name, '/') == NULL)
-    {
-      const char *f;
-
-      f = strrchr (s->filename, '/');
-      if (f != NULL
-	  && strcmp (f + 1, global_needed->name) == 0)
-	{
-	  global_found = true;
-	  return;
-	}
-    }
 }
 
 EOF
@@ -1030,7 +1030,7 @@ gld${EMULATION_NAME}_place_orphan (file,
 
   secname = bfd_get_section_name (s->owner, s);
 
-  if (! config.unique_orphan_sections)
+  if (! config.unique_orphan_sections && ! unique_section_p (secname))
     {
       /* Look through the script to see where to place this section.  */
       os = lang_output_section_find (secname);
@@ -1075,7 +1075,7 @@ gld${EMULATION_NAME}_place_orphan (file,
   if ((s->flags & SEC_ALLOC) == 0)
     ;
   else if ((s->flags & SEC_LOAD) != 0
-	   && strncmp (secname, ".note", 4) == 0
+	   && strncmp (secname, ".note", 5) == 0
 	   && HAVE_SECTION (hold_interp, ".interp"))
     place = &hold_interp;
   else if ((s->flags & SEC_HAS_CONTENTS) == 0


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