summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Storsjo <martin@martin.st>2018-03-14 20:17:16 +0000
committerMartin Storsjo <martin@martin.st>2018-03-14 20:17:16 +0000
commit5351891b553e6bb6bd0cb1e8c2c99128c75cc76e (patch)
treeb0d96389c5ba2b57c3bde3cbbf5e0cc36f9a2f85
parent36f678b48a3055434ce771bd9e2f9c93fe93ad38 (diff)
downloadbcm5719-llvm-5351891b553e6bb6bd0cb1e8c2c99128c75cc76e.tar.gz
bcm5719-llvm-5351891b553e6bb6bd0cb1e8c2c99128c75cc76e.zip
[COFF] Add support for the GNU ld flag --kill-at
GNU ld has got a number of different flags for adjusting how to behave around stdcall functions. The --kill-at flag strips the trailing sdcall suffix from exported functions (which otherwise is included by default in MinGW setups). This also strips it from the corresponding import library though. That makes it hard to link to such an import library from code that calls the functions - but this matches what GNU ld does with this flag. Therefore, this flag is probably not sensibly used together with import libraries, but probably mostly when creating some sort of plugin, or if creating the import library separately with dlltool. Differential Revision: https://reviews.llvm.org/D44292 llvm-svn: 327561
-rw-r--r--lld/COFF/Config.h1
-rw-r--r--lld/COFF/Driver.cpp4
-rw-r--r--lld/COFF/DriverUtils.cpp29
-rw-r--r--lld/COFF/Options.td1
-rw-r--r--lld/test/COFF/def-export-stdcall.s33
5 files changed, 67 insertions, 1 deletions
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index a120435a69f..31fb2f2da4a 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -190,6 +190,7 @@ struct Configuration {
bool WarnMissingOrderSymbol = true;
bool WarnLocallyDefinedImported = true;
bool Incremental = true;
+ bool KillAt = false;
};
extern Configuration *Config;
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 6b16c60d1ff..5fb56e4c5d8 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -1073,6 +1073,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
if (Args.hasArg(OPT_lldsavetemps))
Config->SaveTemps = true;
+ // Handle /kill-at
+ if (Args.hasArg(OPT_kill_at))
+ Config->KillAt = true;
+
// Handle /lldltocache
if (auto *Arg = Args.getLastArg(OPT_lldltocache))
Config->LTOCache = Arg->getValue();
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp
index 64f15e27f8c..0b705f483c8 100644
--- a/lld/COFF/DriverUtils.cpp
+++ b/lld/COFF/DriverUtils.cpp
@@ -582,6 +582,26 @@ static StringRef undecorate(StringRef Sym) {
return Sym.startswith("_") ? Sym.substr(1) : Sym;
}
+// Convert stdcall/fastcall style symbols into unsuffixed symbols,
+// with or without a leading underscore. (MinGW specific.)
+static StringRef killAt(StringRef Sym, bool Prefix) {
+ if (Sym.empty())
+ return Sym;
+ // Strip any trailing stdcall suffix
+ Sym = Sym.substr(0, Sym.find('@', 1));
+ if (!Sym.startswith("@")) {
+ if (Prefix && !Sym.startswith("_"))
+ return Saver.save("_" + Sym);
+ return Sym;
+ }
+ // For fastcall, remove the leading @ and replace it with an
+ // underscore, if prefixes are used.
+ Sym = Sym.substr(1);
+ if (Prefix)
+ Sym = Saver.save("_" + Sym);
+ return Sym;
+}
+
// Performs error checking on all /export arguments.
// It also sets ordinals.
void fixupExports() {
@@ -614,6 +634,15 @@ void fixupExports() {
}
}
+ if (Config->KillAt && Config->Machine == I386) {
+ for (Export &E : Config->Exports) {
+ E.Name = killAt(E.Name, true);
+ E.ExportName = killAt(E.ExportName, false);
+ E.ExtName = killAt(E.ExtName, true);
+ E.SymbolName = killAt(E.SymbolName, true);
+ }
+ }
+
// Uniquefy by name.
DenseMap<StringRef, Export *> Map(Config->Exports.size());
std::vector<Export> V;
diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index d9531b5557d..7373619dad3 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -126,6 +126,7 @@ def help_q : Flag<["/?", "-?"], "">, Alias<help>;
def debug_ghash : F<"debug:ghash">;
def debug_dwarf : F<"debug:dwarf">;
def export_all_symbols : F<"export-all-symbols">;
+def kill_at : F<"kill-at">;
def lldmingw : F<"lldmingw">;
def msvclto : F<"msvclto">;
def output_def : Joined<["/", "-"], "output-def:">;
diff --git a/lld/test/COFF/def-export-stdcall.s b/lld/test/COFF/def-export-stdcall.s
index db251406584..9fbdf99db66 100644
--- a/lld/test/COFF/def-export-stdcall.s
+++ b/lld/test/COFF/def-export-stdcall.s
@@ -44,7 +44,8 @@
# DECORATED-EXPORTS: Name: vectorcall@@8
-# RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall@8\n @fastcall@8" > %t.def
+# GNU tools don't support vectorcall at the moment, but test it for completeness.
+# RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall@8\n @fastcall@8\n vectorcall@@8" > %t.def
# RUN: lld-link -lldmingw -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib
# RUN: llvm-readobj %t.lib | FileCheck -check-prefix DECORATED-MINGW-IMPLIB %s
# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix DECORATED-MINGW-EXPORTS %s
@@ -55,9 +56,39 @@
# DECORATED-MINGW-IMPLIB: Name type: noprefix
# DECORATED-MINGW-IMPLIB-NEXT: __imp__stdcall@8
# DECORATED-MINGW-IMPLIB-NEXT: _stdcall@8
+# GNU tools don't support vectorcall, but this test is just to track that
+# lld's behaviour remains consistent over time.
+# DECORATED-MINGW-IMPLIB: Name type: name
+# DECORATED-MINGW-IMPLIB-NEXT: __imp_vectorcall@@8
+# DECORATED-MINGW-IMPLIB-NEXT: vectorcall@@8
# DECORATED-MINGW-EXPORTS: Name: @fastcall@8
# DECORATED-MINGW-EXPORTS: Name: stdcall@8
+# DECORATED-MINGW-EXPORTS: Name: vectorcall@@8
+
+# RUN: lld-link -lldmingw -kill-at -entry:dllmain -dll -def:%t.deco-mingw.def %t.obj -out:%t.dll -implib:%t.lib
+# RUN: llvm-readobj %t.lib | FileCheck -check-prefix MINGW-KILL-AT-IMPLIB %s
+# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix MINGW-KILL-AT-EXPORTS %s
+
+# RUN: lld-link -lldmingw -kill-at -entry:dllmain -dll %t.obj -out:%t.dll -implib:%t.lib
+# RUN: llvm-readobj %t.lib | FileCheck -check-prefix MINGW-KILL-AT-IMPLIB %s
+# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix MINGW-KILL-AT-EXPORTS %s
+
+# MINGW-KILL-AT-IMPLIB: Name type: noprefix
+# MINGW-KILL-AT-IMPLIB: __imp__fastcall
+# MINGW-KILL-AT-IMPLIB-NEXT: _fastcall
+# MINGW-KILL-AT-IMPLIB: Name type: noprefix
+# MINGW-KILL-AT-IMPLIB-NEXT: __imp__stdcall
+# MINGW-KILL-AT-IMPLIB-NEXT: _stdcall
+# GNU tools don't support vectorcall, but this test is just to track that
+# lld's behaviour remains consistent over time.
+# MINGW-KILL-AT-IMPLIB: Name type: noprefix
+# MINGW-KILL-AT-IMPLIB-NEXT: __imp__vectorcall
+# MINGW-KILL-AT-IMPLIB-NEXT: _vectorcall
+
+# MINGW-KILL-AT-EXPORTS: Name: fastcall
+# MINGW-KILL-AT-EXPORTS: Name: stdcall
+# MINGW-KILL-AT-EXPORTS: Name: vectorcall
.def _stdcall@8;
OpenPOWER on IntegriCloud