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]

[RFC PATCH] add --force-section-merge flag


It seems that for relocatable links, ld does not perform string literal
merging. That is kind of understandable, since it would normally just be
wasted effort, as one doesn't lose any opportunities by postponing that
to the final link.

However, for VxWorks, all modules are built with -r, and there is no
final link - or rather, that is done by the runtime loader. By that
time, merging strings is too late to have any benefit; the memory is
already wasted. Since many VxWorks targets have rather limited disk and
RAM, saving even a few KB is worthwhile.

This is an attempt at adding a --force-section-merge command line flag,
similar to the --force-group-allocation flag. It is almost entirely
mechanical, and I fear that it can't be that easy (for example, there
might be some relocation fixup code hidden under a
!bfd_link_relocatable (&link_info)).

Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
---
 include/bfdlink.h | 3 +++
 ld/ld.h           | 3 +++
 ld/ld.texinfo     | 8 ++++++++
 ld/ldlang.c       | 9 ++++++---
 ld/ldlex.h        | 1 +
 ld/ldmain.c       | 6 ++++++
 ld/lexsup.c       | 6 ++++++
 7 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/include/bfdlink.h b/include/bfdlink.h
index e7c7836f7f..6aceddc30a 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -348,6 +348,9 @@ struct bfd_link_info
   /* TRUE if section groups should be resolved.  */
   unsigned int resolve_section_groups: 1;
 
+  /* TRUE if SEC_MERGE sections should be merged.  */
+  unsigned int merge_sections: 1;
+
   /* Which symbols to strip.  */
   ENUM_BITFIELD (bfd_link_strip) strip : 2;
 
diff --git a/ld/ld.h b/ld/ld.h
index 162e156f08..18707a39f0 100644
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -177,6 +177,9 @@ typedef struct
      in the linker script.  */
   bfd_boolean force_group_allocation;
 
+  /* If set, do merge SEC_MERGE sections even for relocatable output.  */
+  bfd_boolean force_section_merge;
+
   /* Big or little endian as set on command line.  */
   enum endian_enum endian;
 
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 950c794708..acfe220090 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1514,6 +1514,14 @@ change the behaviour of a relocatable link (@samp{-r}).  The script
 command @code{FORCE_GROUP_ALLOCATION} has the same
 effect. @xref{Miscellaneous Commands}.
 
+@kindex --force-section-merge
+@item --force-section-merge
+This option causes the linker to perform merging of identical constants
+in sections with the SEC_MERGE flag, in particular merging identical
+string literals.  This is the default behaviour for a final link but
+this option can be used to change the behaviour of a relocatable link
+(@samp{-r}).
+
 @cindex symbols, from command line
 @kindex --defsym=@var{symbol}=@var{exp}
 @item --defsym=@var{symbol}=@var{expression}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 4ce0f5115b..ef61e47385 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -7162,15 +7162,18 @@ lang_process (void)
   /* Find any sections not attached explicitly and handle them.  */
   lang_place_orphans ();
 
-  if (!bfd_link_relocatable (&link_info))
+  if (link_info.merge_sections)
     {
-      asection *found;
-
       /* Merge SEC_MERGE sections.  This has to be done after GC of
 	 sections, so that GCed sections are not merged, but before
 	 assigning dynamic symbols, since removing whole input sections
 	 is hard then.  */
       bfd_merge_sections (link_info.output_bfd, &link_info);
+    }
+
+  if (!bfd_link_relocatable (&link_info))
+    {
+      asection *found;
 
       /* Look for a text section and set the readonly attribute in it.  */
       found = bfd_get_section_by_name (link_info.output_bfd, ".text");
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 5aa7f6bc3e..467f30763c 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -147,6 +147,7 @@ enum option_values
   OPTION_REQUIRE_DEFINED_SYMBOL,
   OPTION_ORPHAN_HANDLING,
   OPTION_FORCE_GROUP_ALLOCATION,
+  OPTION_FORCE_SECTION_MERGE,
 };
 
 /* The initial parser states.  */
diff --git a/ld/ldmain.c b/ld/ldmain.c
index ee5ab1166a..c9fb802af7 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -392,6 +392,12 @@ main (int argc, char **argv)
   else
     link_info.resolve_section_groups = FALSE;
 
+  if (command_line.force_section_merge
+      || !bfd_link_relocatable (&link_info))
+    link_info.merge_sections = TRUE;
+  else
+    link_info.merge_sections = FALSE;
+
   if (command_line.print_output_format)
     info_msg ("%s\n", lang_get_output_target ());
 
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 08106bcc1a..bd8625340d 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -115,6 +115,9 @@ static const struct ld_option ld_options[] =
   { {"force-group-allocation", no_argument, NULL,
      OPTION_FORCE_GROUP_ALLOCATION},
     '\0', NULL, N_("Force group members out of groups"), TWO_DASHES },
+  { {"force-section-merge", no_argument, NULL,
+     OPTION_FORCE_SECTION_MERGE},
+    '\0', NULL, N_("Force merge of SEC_MERGE sections"), TWO_DASHES },
   { {"entry", required_argument, NULL, 'e'},
     'e', N_("ADDRESS"), N_("Set start address"), TWO_DASHES },
   { {"export-dynamic", no_argument, NULL, OPTION_EXPORT_DYNAMIC},
@@ -773,6 +776,9 @@ parse_args (unsigned argc, char **argv)
         case OPTION_FORCE_GROUP_ALLOCATION:
           command_line.force_group_allocation = TRUE;
           break;
+        case OPTION_FORCE_SECTION_MERGE:
+          command_line.force_section_merge = TRUE;
+          break;
 	case OPTION_DEFSYM:
 	  lex_string = optarg;
 	  lex_redirect (optarg, "--defsym", ++defsym_count);
-- 
2.16.4


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