From fba503a78c50d6134943245d55e820f53e8f19cd Mon Sep 17 00:00:00 2001
From: Erinn Clark <erinn@torproject.org>
Date: Fri, 8 Aug 2014 14:23:44 -0400
Subject: [PATCH] add relocation section so Windows bundles can have ASLR

Patch by skruffy.
---
 ld/emultempl/pe.em  |  7 ++++++
 ld/emultempl/pep.em | 11 ++++++++--
 ld/pe-dll.c         | 63 ++++++++++++++++++++++++++++++-----------------------
 ld/pe-dll.h         |  1 +
 4 files changed, 53 insertions(+), 29 deletions(-)

diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 339b7c5..3958b81 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -272,6 +272,7 @@ fragment <<EOF
 #define OPTION_INSERT_TIMESTAMP		(OPTION_TERMINAL_SERVER_AWARE + 1)
 #define OPTION_NO_INSERT_TIMESTAMP	(OPTION_INSERT_TIMESTAMP + 1)
 #define OPTION_BUILD_ID			(OPTION_NO_INSERT_TIMESTAMP + 1)
+#define OPTION_ENABLE_RELOC_SECTION	(OPTION_BUILD_ID + 1)
 
 static void
 gld${EMULATION_NAME}_add_options
@@ -315,6 +316,7 @@ gld${EMULATION_NAME}_add_options
     {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
     {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
     {"exclude-all-symbols", no_argument, NULL, OPTION_EXCLUDE_ALL_SYMBOLS},
+    {"enable-reloc-section", no_argument, NULL, OPTION_ENABLE_RELOC_SECTION},
     {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
     {"exclude-modules-for-implib", required_argument, NULL, OPTION_EXCLUDE_MODULES_FOR_IMPLIB},
     {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
@@ -782,6 +784,9 @@ gld${EMULATION_NAME}_handle_option (int optc)
     case OPTION_EXCLUDE_ALL_SYMBOLS:
       pe_dll_exclude_all_symbols = 1;
       break;
+    case OPTION_ENABLE_RELOC_SECTION:
+      pe_dll_enable_reloc_section = 1;
+      break;
     case OPTION_EXCLUDE_LIBS:
       pe_dll_add_excludes (optarg, EXCLUDELIBS);
       break;
@@ -2076,6 +2081,8 @@ gld_${EMULATION_NAME}_finish (void)
 #if !defined(TARGET_IS_shpe)
       || (!bfd_link_relocatable (&link_info)
 	  && pe_def_file->num_exports != 0)
+      || (!bfd_link_relocatable (&link_info)
+          && pe_dll_enable_reloc_section)
 #endif
     )
     {
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index c253d2f..fccbd63 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -246,7 +246,8 @@ enum options
   OPTION_INSERT_TIMESTAMP,
   OPTION_NO_INSERT_TIMESTAMP,
   OPTION_TERMINAL_SERVER_AWARE,
-  OPTION_BUILD_ID
+  OPTION_BUILD_ID,
+  OPTION_ENABLE_RELOC_SECTION
 };
 
 static void
@@ -288,6 +289,7 @@ gld${EMULATION_NAME}_add_options
     {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
     {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
     {"exclude-all-symbols", no_argument, NULL, OPTION_EXCLUDE_ALL_SYMBOLS},
+    {"enable-reloc-section", no_argument, NULL, OPTION_ENABLE_RELOC_SECTION},
     {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
     {"exclude-modules-for-implib", required_argument, NULL, OPTION_EXCLUDE_MODULES_FOR_IMPLIB},
     {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
@@ -739,6 +741,9 @@ gld${EMULATION_NAME}_handle_option (int optc)
     case OPTION_EXCLUDE_ALL_SYMBOLS:
       pep_dll_exclude_all_symbols = 1;
       break;
+    case OPTION_ENABLE_RELOC_SECTION:
+      pe_dll_enable_reloc_section = 1;
+      break;
     case OPTION_EXCLUDE_LIBS:
       pep_dll_add_excludes (optarg, EXCLUDELIBS);
       break;
@@ -1857,7 +1862,9 @@ gld_${EMULATION_NAME}_finish (void)
 #ifdef DLL_SUPPORT
   if (bfd_link_pic (&link_info)
       || (!bfd_link_relocatable (&link_info)
-	  && pep_def_file->num_exports != 0))
+          && pe_dll_enable_reloc_section)
+      || (!bfd_link_relocatable (&link_info)
+          && pep_def_file->num_exports != 0))
     {
       pep_dll_fill_sections (link_info.output_bfd, &link_info);
       if (command_line.out_implib_filename)
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index c398f23..3797f1a 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -151,6 +151,7 @@ def_file * pe_def_file = 0;
 int pe_dll_export_everything = 0;
 int pe_dll_exclude_all_symbols = 0;
 int pe_dll_do_default_excludes = 1;
+int pe_dll_enable_reloc_section = 0;
 int pe_dll_kill_ats = 0;
 int pe_dll_stdcall_aliases = 0;
 int pe_dll_warn_dup_exports = 0;
@@ -3430,8 +3431,15 @@ pe_dll_build_sections (bfd *abfd, struct bfd_link_info *info)
   process_def_file_and_drectve (abfd, info);
 
   if (pe_def_file->num_exports == 0 && !bfd_link_pic (info))
-    return;
-
+    {
+      if (pe_dll_enable_reloc_section)
+        {
+          build_filler_bfd (0);
+          pe_output_file_set_long_section_names (filler_bfd);
+        }
+      return;
+    }
+    
   generate_edata (abfd, info);
   build_filler_bfd (1);
   pe_output_file_set_long_section_names (filler_bfd);
@@ -3446,13 +3454,9 @@ pe_exe_build_sections (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
   pe_output_file_set_long_section_names (filler_bfd);
 }
 
-void
-pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
+static void
+pe_dll_create_reloc (bfd *abfd, struct bfd_link_info *info)
 {
-  pe_dll_id_target (bfd_get_target (abfd));
-  pe_output_file_set_long_section_names (abfd);
-  image_base = pe_data (abfd)->pe_opthdr.ImageBase;
-
   generate_reloc (abfd, info);
   if (reloc_sz > 0)
     {
@@ -3469,38 +3473,43 @@ pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
       lang_do_assignments (lang_final_phase_enum);
     }
 
-  fill_edata (abfd, info);
-
-  if (bfd_link_dll (info))
-    pe_data (abfd)->dll = 1;
-
-  edata_s->contents = edata_d;
   reloc_s->contents = reloc_d;
 }
 
 void
-pe_exe_fill_sections (bfd *abfd, struct bfd_link_info *info)
+pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
 {
+  if (!reloc_s && !edata_s)
+    return;
   pe_dll_id_target (bfd_get_target (abfd));
   pe_output_file_set_long_section_names (abfd);
   image_base = pe_data (abfd)->pe_opthdr.ImageBase;
 
-  generate_reloc (abfd, info);
-  if (reloc_sz > 0)
+  if (reloc_s)
+    pe_dll_create_reloc (abfd, info);
+
+  if (edata_s)
     {
-      bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
+      fill_edata (abfd, info);
+      edata_s->contents = edata_d;
+    }
 
-      /* Resize the sections.  */
-      lang_reset_memory_regions ();
-      lang_size_sections (NULL, TRUE);
+  if (bfd_link_pic (info) && !bfd_link_pie (info))
+    pe_data (abfd)->dll = 1;
 
-      /* Redo special stuff.  */
-      ldemul_after_allocation ();
 
-      /* Do the assignments again.  */
-      lang_do_assignments (lang_final_phase_enum);
-    }
-  reloc_s->contents = reloc_d;
+}
+
+void
+pe_exe_fill_sections (bfd *abfd, struct bfd_link_info *info)
+{
+  if (!reloc_s)
+    return;
+  pe_dll_id_target (bfd_get_target (abfd));
+  pe_output_file_set_long_section_names (abfd);
+  image_base = pe_data (abfd)->pe_opthdr.ImageBase;
+
+  pe_dll_create_reloc (abfd, info);
 }
 
 bfd_boolean
diff --git a/ld/pe-dll.h b/ld/pe-dll.h
index 48d169b..05ff72b 100644
--- a/ld/pe-dll.h
+++ b/ld/pe-dll.h
@@ -30,6 +30,7 @@ extern def_file *pe_def_file;
 extern int pe_dll_export_everything;
 extern int pe_dll_exclude_all_symbols;
 extern int pe_dll_do_default_excludes;
+extern int pe_dll_enable_reloc_section;
 extern int pe_dll_kill_ats;
 extern int pe_dll_stdcall_aliases;
 extern int pe_dll_warn_dup_exports;
-- 
2.1.4

