summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
Diffstat (limited to 'lld')
-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