blob: e7c40d02988053ee7ac7c10f496075753bfefedb [file] [log] [blame]
From 62ab108bf89332d41173dc45914200797d1e792d Mon Sep 17 00:00:00 2001
From: Jeremy Drake <github@jdrake.com>
Date: Thu, 10 Sep 2020 10:28:28 -0700
Subject: [PATCH] ld option to move default bases under 4GB.
Some (buggy) programs have 'latent pointer truncation' issues, and
setting the ImageBase below 4GB indicates to Windows that it's not safe
to relocate these using ASLR in such a way as to trigger them.
---
ld/emultempl/pep.em | 50 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 47 insertions(+), 3 deletions(-)
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index 639a9e96cc..0918a68059 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -107,18 +107,26 @@ fragment <<EOF
#define NT_EXE_IMAGE_BASE \
((bfd_vma) (${move_default_addr_high} ? 0x100400000LL \
: 0x140000000LL))
+#undef NT_EXE_IMAGE_BASE_LOW
+#define NT_EXE_IMAGE_BASE_LOW ((bfd_vma) 0x400000LL)
#undef NT_DLL_IMAGE_BASE
#define NT_DLL_IMAGE_BASE \
((bfd_vma) (${move_default_addr_high} ? 0x400000000LL \
: 0x180000000LL))
+#undef NT_DLL_IMAGE_BASE_LOW
+#define NT_DLL_IMAGE_BASE_LOW ((bfd_vma) 0x10000000LL)
#undef NT_DLL_AUTO_IMAGE_BASE
#define NT_DLL_AUTO_IMAGE_BASE \
((bfd_vma) (${move_default_addr_high} ? 0x400000000LL \
: 0x1C0000000LL))
+#undef NT_DLL_AUTO_IMAGE_BASE_LOW
+#define NT_DLL_AUTO_IMAGE_BASE_LOW ((bfd_vma) 0x61300000LL)
#undef NT_DLL_AUTO_IMAGE_MASK
#define NT_DLL_AUTO_IMAGE_MASK \
((bfd_vma) (${move_default_addr_high} ? 0x1ffff0000LL \
: 0x1ffff0000LL))
+#undef NT_DLL_AUTO_IMAGE_MASK_LOW
+#define NT_DLL_AUTO_IMAGE_MASK_LOW ((bfd_vma) 0x0ffc0000LL)
#else
#undef NT_EXE_IMAGE_BASE
#define NT_EXE_IMAGE_BASE \
@@ -151,6 +159,7 @@ static int support_old_code = 0;
static lang_assignment_statement_type *image_base_statement = 0;
static unsigned short pe_dll_characteristics = DEFAULT_DLL_CHARACTERISTICS;
static bfd_boolean insert_timestamp = TRUE;
+static bfd_boolean high_default_bases = TRUE;
static const char *emit_build_id;
#ifdef DLL_SUPPORT
@@ -260,7 +269,9 @@ enum options
OPTION_DISABLE_NO_SEH,
OPTION_DISABLE_NO_BIND,
OPTION_DISABLE_WDM_DRIVER,
- OPTION_DISABLE_TERMINAL_SERVER_AWARE
+ OPTION_DISABLE_TERMINAL_SERVER_AWARE,
+ OPTION_DEFAULT_IMAGE_BASE_LOW,
+ OPTION_DEFAULT_IMAGE_BASE_HIGH
};
static void
@@ -349,6 +360,10 @@ gld${EMULATION_NAME}_add_options
{"disable-no-bind", no_argument, NULL, OPTION_DISABLE_NO_BIND},
{"disable-wdmdriver", no_argument, NULL, OPTION_DISABLE_WDM_DRIVER},
{"disable-tsaware", no_argument, NULL, OPTION_DISABLE_TERMINAL_SERVER_AWARE},
+#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
+ {"default-image-base-low", no_argument, NULL, OPTION_DEFAULT_IMAGE_BASE_LOW},
+ {"default-image-base-high", no_argument, NULL, OPTION_DEFAULT_IMAGE_BASE_HIGH},
+#endif
{NULL, no_argument, NULL, 0}
};
@@ -486,6 +501,10 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
fprintf (file, _(" --[disable-]tsaware Image is Terminal Server aware\n"));
fprintf (file, _(" --build-id[=STYLE] Generate build ID\n"));
#endif
+#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
+ fprintf (file, _(" --default-image-base-low Default image bases under 4GB\n"));
+ fprintf (file, _(" --default-image-base-high Default image bases over 4GB\n"));
+#endif
}
@@ -893,6 +912,12 @@ gld${EMULATION_NAME}_handle_option (int optc)
if (strcmp (optarg, "none"))
emit_build_id = xstrdup (optarg);
break;
+ case OPTION_DEFAULT_IMAGE_BASE_LOW:
+ high_default_bases = FALSE;
+ break;
+ case OPTION_DEFAULT_IMAGE_BASE_HIGH:
+ high_default_bases = TRUE;
+ break;
}
/* Set DLLCharacteristics bits */
@@ -932,7 +957,14 @@ static bfd_vma
compute_dll_image_base (const char *ofile)
{
bfd_vma hash = (bfd_vma) strhash (ofile);
- return NT_DLL_AUTO_IMAGE_BASE + ((hash << 16) & NT_DLL_AUTO_IMAGE_MASK);
+#ifdef TARGET_IS_i386pep
+ if (high_default_bases)
+#endif
+ return NT_DLL_AUTO_IMAGE_BASE + ((hash << 16) & NT_DLL_AUTO_IMAGE_MASK);
+#ifdef TARGET_IS_i386pep
+ else
+ return NT_DLL_AUTO_IMAGE_BASE_LOW + ((hash << 16) & NT_DLL_AUTO_IMAGE_MASK_LOW);
+#endif
}
#endif
@@ -957,13 +989,25 @@ gld_${EMULATION_NAME}_set_symbols (void)
#ifdef DLL_SUPPORT
init[IMAGEBASEOFF].value = (pep_enable_auto_image_base
? compute_dll_image_base (output_filename)
+#ifdef TARGET_IS_i386pep
+ : (high_default_bases
+ ? NT_DLL_IMAGE_BASE
+ : NT_DLL_IMAGE_BASE_LOW));
+#else
: NT_DLL_IMAGE_BASE);
+#endif
#else
- init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE;
+ init[IMAGEBASEOFF].value = (high_default_bases ? NT_DLL_IMAGE_BASE : NT_DLL_IMAGE_BASE_LOW);
#endif
}
else
+#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
+ init[IMAGEBASEOFF].value = (high_default_bases
+ ? NT_EXE_IMAGE_BASE
+ : NT_EXE_IMAGE_BASE_LOW);
+#else
init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE;
+#endif
init[MSIMAGEBASEOFF].value = init[IMAGEBASEOFF].value;
}
--
2.28.0.windows.1