From 6e739c9296d16efed9cf2b0d352cd21fdd57d236 Mon Sep 17 00:00:00 2001
From: fincs <fincs.alt1@gmail.com>
Date: Sun, 2 Oct 2016 12:27:52 +0200
Subject: [PATCH] Implement and document --gc-keep-exported

---
 bfd/ChangeLog     |  6 ++++++
 bfd/elflink.c     |  3 ++-
 include/ChangeLog |  4 ++++
 include/bfdlink.h |  3 +++
 ld/ChangeLog      |  6 ++++++
 ld/ld.texinfo     | 12 ++++++++++++
 ld/ldlex.h        |  1 +
 ld/lexsup.c       |  6 ++++++
 8 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4f859c565a..0da4bde49f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2016-12-15  fincs  <fincs.alt1@gmail.com>
+
+	* elflink.c (bfd_elf_gc_mark_dynamic_ref_symbol): Add handling
+	for info->gc_keep_exported.
+	(bfd_elf_gc_sections): Add handling for info->gc_keep_exported.
+
 2016-08-03  Tristan Gingold  <gingold@adacore.com>
 
 	* version.m4: Bump version to 2.27
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 3e249400f6..e34216ff09 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12894,6 +12894,7 @@ bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf)
 	      && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL
 	      && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN
 	      && (!bfd_link_executable (info)
+		  || info->gc_keep_exported
 		  || info->export_dynamic
 		  || (h->dynamic
 		      && d != NULL
@@ -13012,7 +13013,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
     return FALSE;
 
   /* Mark dynamically referenced symbols.  */
-  if (htab->dynamic_sections_created)
+  if (htab->dynamic_sections_created || info->gc_keep_exported)
     elf_link_hash_traverse (htab, bed->gc_mark_dynamic_ref, info);
 
   /* Grovel through relocs to find out who stays ...  */
diff --git a/include/ChangeLog b/include/ChangeLog
index a766ecf9dc..7b9e2da448 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2016-12-15  fincs  <fincs.alt1@gmail.com>
+
+	* bfdlink.h (struct bfd_link_info): Add gc_keep_exported.
+
 2016-06-30  Matthew Wahab  <matthew.wahab@arm.com>
 
 	* opcode/arm.h (ARM_ARCH_V8_2a): Add FPU_NEON_EXT_RDMA to the set
diff --git a/include/bfdlink.h b/include/bfdlink.h
index b392d54b35..d6a3bb701f 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -325,6 +325,9 @@ struct bfd_link_info
   /* TRUE if unreferenced sections should be removed.  */
   unsigned int gc_sections: 1;
 
+  /* TRUE if exported symbols should be kept during section gc.  */
+  unsigned int gc_keep_exported: 1;
+
   /* TRUE if every symbol should be reported back via the notice
      callback.  */
   unsigned int notice_all: 1;
diff --git a/ld/ChangeLog b/ld/ChangeLog
index a57cd66522..c3d9bf49f9 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,9 @@
+2016-12-15  fincs  <fincs.alt1@gmail.com>
+
+	* ld.texinfo: Document --gc-keep-exported.
+	* ldlex.h (enum option_values): Add OPTION_GC_KEEP_EXPORTED.
+	* lexsup.c (parse_args): Add handling for --gc-keep-exported.
+
 2016-08-03  Tristan Gingold  <gingold@adacore.com>
 
 	* configure: Regenerate.
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index bc16764b05..30ccd1deae 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1558,6 +1558,18 @@ default behaviour (of not listing the sections that are removed) can
 be restored by specifying @samp{--no-print-gc-sections} on the command
 line.
 
+@kindex --gc-keep-exported
+@cindex garbage collection
+@item --gc-keep-exported
+When @samp{--gc-sections} is enabled, this option prevents garbage
+collection of unused input sections that contain global symbols having
+default or protected visibility.  This option is intended to be used for
+executables where unreferenced sections would otherwise be garbage
+collected regardless of the external visibility of contained symbols.
+Note that this option has no effect when linking shared objects since
+it is already the default behaviour.  This option is only supported for
+ELF format targets.
+
 @kindex --print-output-format
 @cindex output format
 @item --print-output-format
diff --git a/ld/ldlex.h b/ld/ldlex.h
index cf943e425f..cbe3267d0d 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -100,6 +100,7 @@ enum option_values
   OPTION_NO_GC_SECTIONS,
   OPTION_PRINT_GC_SECTIONS,
   OPTION_NO_PRINT_GC_SECTIONS,
+  OPTION_GC_KEEP_EXPORTED,
   OPTION_HASH_SIZE,
   OPTION_CHECK_SECTIONS,
   OPTION_NO_CHECK_SECTIONS,
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 6d28e9142b..f4f0d59485 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -333,6 +333,9 @@ static const struct ld_option ld_options[] =
   { {"no-print-gc-sections", no_argument, NULL, OPTION_NO_PRINT_GC_SECTIONS},
     '\0', NULL, N_("Do not list removed unused sections"),
     TWO_DASHES },
+  { {"gc-keep-exported", no_argument, NULL, OPTION_GC_KEEP_EXPORTED},
+    '\0', NULL, N_("Keep exported symbols when removing unused sections"),
+    TWO_DASHES },
   { {"hash-size=<NUMBER>", required_argument, NULL, OPTION_HASH_SIZE},
     '\0', NULL, N_("Set default hash table size close to <NUMBER>"),
     TWO_DASHES },
@@ -858,6 +861,9 @@ parse_args (unsigned argc, char **argv)
 	case OPTION_PRINT_GC_SECTIONS:
 	  link_info.print_gc_sections = TRUE;
 	  break;
+	case OPTION_GC_KEEP_EXPORTED:
+	  link_info.gc_keep_exported = TRUE;
+	  break;
 	case OPTION_HELP:
 	  help ();
 	  xexit (0);
-- 
2.11.0

