diff options
Diffstat (limited to 'lld')
-rw-r--r-- | lld/COFF/Config.h | 1 | ||||
-rw-r--r-- | lld/COFF/Driver.cpp | 4 | ||||
-rw-r--r-- | lld/COFF/DriverUtils.cpp | 29 | ||||
-rw-r--r-- | lld/COFF/Options.td | 1 | ||||
-rw-r--r-- | lld/test/COFF/def-export-stdcall.s | 33 |
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; |