[lld] 7f0e6c3 - [LLD] [COFF] Add options for disabling auto import and runtime pseudo relocs

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Thu May 14 03:05:29 PDT 2020


Author: Martin Storsjö
Date: 2020-05-14T13:05:14+03:00
New Revision: 7f0e6c31c25530352aa6e4cd9e2bdc4381368eba

URL: https://github.com/llvm/llvm-project/commit/7f0e6c31c25530352aa6e4cd9e2bdc4381368eba
DIFF: https://github.com/llvm/llvm-project/commit/7f0e6c31c25530352aa6e4cd9e2bdc4381368eba.diff

LOG: [LLD] [COFF] Add options for disabling auto import and runtime pseudo relocs

Allow disabling either the full auto import feature, or just
forbidding the cases that require runtime fixups.

As long as all auto imported variables are referenced from separate
.refptr$<name> sections, we can alias them on top of the IAT entries
and don't actually need any runtime fixups via pseudo relocations.
LLVM generates references to variables in .refptr stubs, if it
isn't known that the variable for sure is defined in the same object
module. Runtime pseudo relocs are needed if the addresses of auto
imported variables are used in constant initializers though.

Fixing up runtime pseudo relocations requires the use of
VirtualProtect (which is disallowed in WinStore/UWP apps) or
VirtualProtectFromApp. To allow any risk of ambiguity, allow
rejecting cases that would require this at the linker stage.

This adds support for the --disable-runtime-pseudo-reloc and
--disable-auto-import options in the MinGW driver (matching GNU ld.bfd)
with corresponding lld private options in the COFF driver.

Differential Revision: https://reviews.llvm.org/D78923

Added: 
    

Modified: 
    lld/COFF/Config.h
    lld/COFF/Driver.cpp
    lld/COFF/Options.td
    lld/COFF/SymbolTable.cpp
    lld/COFF/Writer.cpp
    lld/MinGW/Driver.cpp
    lld/MinGW/Options.td
    lld/test/COFF/autoimport-refptr.s
    lld/test/COFF/autoimport-x86.s
    lld/test/MinGW/driver.test

Removed: 
    


################################################################################
diff  --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 4d7d9e252875..72d826b8bd17 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -235,6 +235,8 @@ struct Configuration {
   bool swaprunNet = false;
   bool thinLTOEmitImportsFiles;
   bool thinLTOIndexOnly;
+  bool autoImport = false;
+  bool pseudoRelocs = false;
 };
 
 extern Configuration *config;

diff  --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 07132345f135..56919d89fd82 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -1580,6 +1580,10 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
   config->debugDwarf = debug == DebugKind::Dwarf;
   config->debugGHashes = debug == DebugKind::GHash;
   config->debugSymtab = debug == DebugKind::Symtab;
+  config->autoImport =
+      args.hasFlag(OPT_auto_import, OPT_auto_import_no, config->mingw);
+  config->pseudoRelocs = args.hasFlag(
+      OPT_runtime_pseudo_reloc, OPT_runtime_pseudo_reloc_no, config->mingw);
 
   // Don't warn about long section names, such as .debug_info, for mingw or when
   // -debug:dwarf is requested.
@@ -1841,9 +1845,11 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
   // Needed for MSVC 2017 15.5 CRT.
   symtab->addAbsolute(mangle("__enclave_config"), 0);
 
-  if (config->mingw) {
+  if (config->pseudoRelocs) {
     symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0);
     symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0);
+  }
+  if (config->mingw) {
     symtab->addAbsolute(mangle("__CTOR_LIST__"), 0);
     symtab->addAbsolute(mangle("__DTOR_LIST__"), 0);
   }
@@ -1901,7 +1907,8 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
     while (run());
   }
 
-  if (config->mingw) {
+  if (config->autoImport) {
+    // MinGW specific.
     // Load any further object files that might be needed for doing automatic
     // imports.
     //

diff  --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index a6181e2d1b8b..212879e1d60b 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -16,6 +16,13 @@ multiclass B<string name, string help_on, string help_off> {
   def _no : F<name#":no">, HelpText<help_off>;
 }
 
+// Same as B<> above, but without help texts, for private undocumented
+// options.
+multiclass B_priv<string name> {
+  def "" : F<name>;
+  def _no : F<name#":no">;
+}
+
 def align   : P<"align", "Section alignment">;
 def aligncomm : P<"aligncomm", "Set common symbol alignment">;
 def alternatename : P<"alternatename", "Define weak alias">;
@@ -184,6 +191,8 @@ def help : F<"help">;
 def help_q : Flag<["/??", "-??", "/?", "-?"], "">, Alias<help>;
 
 // LLD extensions
+defm auto_import : B_priv<"auto-import">;
+defm runtime_pseudo_reloc : B_priv<"runtime-pseudo-reloc">;
 def end_lib : F<"end-lib">,
   HelpText<"Ends group of objects treated as if they were in a library">;
 def exclude_all_symbols : F<"exclude-all-symbols">;

diff  --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index f846af83e900..d4d2a159a639 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -438,7 +438,7 @@ void SymbolTable::resolveRemainingUndefines() {
     if (name.contains("_PchSym_"))
       continue;
 
-    if (config->mingw && handleMinGWAutomaticImport(sym, name))
+    if (config->autoImport && handleMinGWAutomaticImport(sym, name))
       continue;
 
     // Remaining undefined symbols are not fatal if /force is specified.

diff  --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index c7d4fa17bd4c..ffa0a0006f0e 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -969,11 +969,11 @@ void Writer::createMiscChunks() {
   if (config->guardCF != GuardCFLevel::Off)
     createGuardCFTables();
 
-  if (config->mingw) {
+  if (config->autoImport)
     createRuntimePseudoRelocs();
 
+  if (config->mingw)
     insertCtorDtorSymbols();
-  }
 }
 
 // Create .idata section for the DLL-imported symbol table.
@@ -1722,6 +1722,15 @@ void Writer::createRuntimePseudoRelocs() {
     sc->getRuntimePseudoRelocs(rels);
   }
 
+  if (!config->pseudoRelocs) {
+    // Not writing any pseudo relocs; if some were needed, error out and
+    // indicate what required them.
+    for (const RuntimePseudoReloc &rpr : rels)
+      error("automatic dllimport of " + rpr.sym->getName() + " in " +
+            toString(rpr.target->file) + " requires pseudo relocations");
+    return;
+  }
+
   if (!rels.empty())
     log("Writing " + Twine(rels.size()) + " runtime pseudo relocations");
   PseudoRelocTableChunk *table = make<PseudoRelocTableChunk>(rels);

diff  --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp
index c1d10578161d..fbf50280cc8c 100644
--- a/lld/MinGW/Driver.cpp
+++ b/lld/MinGW/Driver.cpp
@@ -295,6 +295,16 @@ bool mingw::link(ArrayRef<const char *> argsArr, bool canExitEarly,
   else
     add("-opt:noref");
 
+  if (args.hasFlag(OPT_enable_auto_import, OPT_disable_auto_import, true))
+    add("-auto-import");
+  else
+    add("-auto-import:no");
+  if (args.hasFlag(OPT_enable_runtime_pseudo_reloc,
+                   OPT_disable_runtime_pseudo_reloc, true))
+    add("-runtime-pseudo-reloc");
+  else
+    add("-runtime-pseudo-reloc:no");
+
   if (auto *a = args.getLastArg(OPT_icf)) {
     StringRef s = a->getValue();
     if (s == "all")

diff  --git a/lld/MinGW/Options.td b/lld/MinGW/Options.td
index 17a964c119b2..a3a84883feb2 100644
--- a/lld/MinGW/Options.td
+++ b/lld/MinGW/Options.td
@@ -20,7 +20,15 @@ def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
   HelpText<"Add a directory to the library search path">;
 def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries">;
 def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">;
+def disable_auto_import: F<"disable-auto-import">,
+    HelpText<"Don't automatically import data symbols from other DLLs without dllimport">;
+def disable_runtime_pseudo_reloc: F<"disable-runtime-pseudo-reloc">,
+    HelpText<"Don't do automatic imports that require runtime fixups">;
 def dynamicbase: F<"dynamicbase">, HelpText<"Enable ASLR">;
+def enable_auto_import: F<"enable-auto-import">,
+    HelpText<"Automatically import data symbols from other DLLs where needed">;
+def enable_runtime_pseudo_reloc: F<"enable-runtime-pseudo-reloc">,
+    HelpText<"Allow automatic imports that require runtime fixups">;
 defm entry: Eq<"entry", "Name of entry point symbol">, MetaVarName<"<entry>">;
 def exclude_all_symbols: F<"exclude-all-symbols">,
     HelpText<"Don't automatically export any symbols">;
@@ -94,7 +102,6 @@ def: Joined<["-"], "O">;
 def: F<"build-id">;
 def: F<"disable-auto-image-base">;
 def: F<"enable-auto-image-base">;
-def: F<"enable-auto-import">, HelpText<"Ignored; listed for libtool compatibility">;
 def: F<"end-group">;
 def: Flag<["--"], "full-shutdown">;
 def: F<"high-entropy-va">;

diff  --git a/lld/test/COFF/autoimport-refptr.s b/lld/test/COFF/autoimport-refptr.s
index 6d69255a737a..d4ccb04b522b 100644
--- a/lld/test/COFF/autoimport-refptr.s
+++ b/lld/test/COFF/autoimport-refptr.s
@@ -4,13 +4,20 @@
 # RUN: llvm-mc -triple=x86_64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj
 # RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib
 
-# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj
+# RUN: llvm-mc -triple=x86_64-windows-gnu %s -defsym listptrs=1 -filetype=obj -o %t.obj
 # RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose
 
 # RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
 # RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASM %s
 # RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=CONTENTS %s
 
+## Check that we can autoimport these variables with pseudo relocs disabled.
+# RUN: llvm-mc -triple=x86_64-windows-gnu %s -defsym listptrs=0 -filetype=obj -o %t.noptrs.obj
+# RUN: lld-link -lldmingw -runtime-pseudo-reloc:no -out:%t.exe -entry:main %t.noptrs.obj %t-lib.lib
+
+## Check that we can't autoimport them with autoimport disabled.
+# RUN: not lld-link -lldmingw -auto-import:no -out:%t.exe -entry:main %t.noptrs.obj %t-lib.lib 2>&1 | FileCheck --check-prefix=NO-AUTOIMPORT %s
+
 # IMPORTS: Import {
 # IMPORTS-NEXT: Name: autoimport-refptr.s.tmp-lib.dll
 # IMPORTS-NEXT: ImportLookupTableRVA: 0x2050
@@ -36,6 +43,8 @@
 # CONTENTS:  140003000 08200040 01000000 08200040 01000000
 # CONTENTS:  140003010 2a000000
 
+# NO-AUTOIMPORT: error: undefined symbol: variable
+
     .global main
     .global localvar
     .text
@@ -47,9 +56,11 @@ main:
     ret
 
     .data
+.if listptrs==1
 relocs:
     .quad __RUNTIME_PSEUDO_RELOC_LIST__
     .quad __RUNTIME_PSEUDO_RELOC_LIST_END__
+.endif
 localvar:
     .int 42
 

diff  --git a/lld/test/COFF/autoimport-x86.s b/lld/test/COFF/autoimport-x86.s
index 2244a1ed868b..62c57b0fb636 100644
--- a/lld/test/COFF/autoimport-x86.s
+++ b/lld/test/COFF/autoimport-x86.s
@@ -4,9 +4,12 @@
 # RUN: llvm-mc -triple=x86_64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj
 # RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib
 
-# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj
+# RUN: llvm-mc -triple=x86_64-windows-gnu -defsym listptrs=1 %s -filetype=obj -o %t.obj
 # RUN: lld-link -lldmingw -debug:symtab -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose
 
+# RUN: llvm-mc -triple=x86_64-windows-gnu -defsym listptrs=0 %s -filetype=obj -o %t.noptrs.obj
+# RUN: not lld-link -lldmingw -runtime-pseudo-reloc:no -debug:symtab -out:%t.exe -entry:main %t.noptrs.obj %t-lib.lib 2>&1 | FileCheck --check-prefix=DISABLED %s
+
 # RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
 # RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASM %s
 # RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=CONTENTS %s
@@ -46,6 +49,8 @@
 # the symbol table.
 # SYMBOLS-NOT: variable
 
+# DISABLED: error: automatic dllimport of variable in {{.*}}/autoimport-x86.s.tmp.noptrs.obj requires pseudo relocations
+
     .global main
     .text
 main:
@@ -54,6 +59,8 @@ main:
     .data
 ptr:
     .quad variable
+.if listptrs==1
 relocs:
     .quad __RUNTIME_PSEUDO_RELOC_LIST__
     .quad __RUNTIME_PSEUDO_RELOC_LIST_END__
+.endif

diff  --git a/lld/test/MinGW/driver.test b/lld/test/MinGW/driver.test
index cf3a223adb92..16b4179a92bc 100644
--- a/lld/test/MinGW/driver.test
+++ b/lld/test/MinGW/driver.test
@@ -223,3 +223,21 @@ UNKNOWN_ARG: error: unknown argument: --foo
 
 RUN: not ld.lld -m i386pep 2>&1 | FileCheck -check-prefix NO_INPUT_FILES %s
 NO_INPUT_FILES: error: no input files
+
+RUN: ld.lld -### -m i386pep foo.o | FileCheck -check-prefix ENABLE_AUTO_IMPORT %s
+RUN: ld.lld -### -m i386pep foo.o --disable-auto-import --enable-auto-import | FileCheck -check-prefix ENABLE_AUTO_IMPORT %s
+RUN: ld.lld -### -m i386pep foo.o -enable-auto-import | FileCheck -check-prefix ENABLE_AUTO_IMPORT %s
+ENABLE_AUTO_IMPORT: -auto-import{{ }}
+
+RUN: ld.lld -### -m i386pep foo.o --disable-auto-import | FileCheck -check-prefix DISABLE_AUTO_IMPORT %s
+RUN: ld.lld -### -m i386pep foo.o -disable-auto-import | FileCheck -check-prefix DISABLE_AUTO_IMPORT %s
+DISABLE_AUTO_IMPORT: -auto-import:no
+
+RUN: ld.lld -### -m i386pep foo.o | FileCheck -check-prefix ENABLE_RUNTIME_PSEUDO_RELOC %s
+RUN: ld.lld -### -m i386pep foo.o --disable-runtime-pseudo-reloc --enable-runtime-pseudo-reloc | FileCheck -check-prefix ENABLE_RUNTIME_PSEUDO_RELOC %s
+RUN: ld.lld -### -m i386pep foo.o -enable-runtime-pseudo-reloc | FileCheck -check-prefix ENABLE_RUNTIME_PSEUDO_RELOC %s
+ENABLE_RUNTIME_PSEUDO_RELOC: -runtime-pseudo-reloc{{ }}
+
+RUN: ld.lld -### -m i386pep foo.o --disable-runtime-pseudo-reloc | FileCheck -check-prefix DISABLE_RUNTIME_PSEUDO_RELOC %s
+RUN: ld.lld -### -m i386pep foo.o -disable-runtime-pseudo-reloc | FileCheck -check-prefix DISABLE_RUNTIME_PSEUDO_RELOC %s
+DISABLE_RUNTIME_PSEUDO_RELOC: -runtime-pseudo-reloc:no


        


More information about the llvm-commits mailing list