Index: COFF/Config.h =================================================================== --- COFF/Config.h +++ COFF/Config.h @@ -189,6 +189,7 @@ bool MinGW = false; bool WarnLocallyDefinedImported = true; bool Incremental = true; + bool KillAt = false; }; extern Configuration *Config; Index: COFF/Driver.cpp =================================================================== --- COFF/Driver.cpp +++ COFF/Driver.cpp @@ -1072,6 +1072,10 @@ 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(); Index: COFF/DriverUtils.cpp =================================================================== --- COFF/DriverUtils.cpp +++ COFF/DriverUtils.cpp @@ -582,6 +582,23 @@ return Sym.startswith("_") ? Sym.substr(1) : Sym; } +// Convert stdcall/fastcall style symbols into unsuffixed symbols, +// with or without a leading underscore. +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("@")) { + // 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 +631,15 @@ } } + 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 Map(Config->Exports.size()); std::vector V; Index: COFF/Options.td =================================================================== --- COFF/Options.td +++ COFF/Options.td @@ -126,6 +126,7 @@ 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:">; Index: MinGW/Driver.cpp =================================================================== --- MinGW/Driver.cpp +++ MinGW/Driver.cpp @@ -154,6 +154,8 @@ Add("-debug:dwarf"); if (Args.hasArg(OPT_large_address_aware)) Add("-largeaddressaware"); + if (Args.hasArg(OPT_kill_at)) + Add("-kill-at"); if (Args.getLastArgValue(OPT_m) != "thumb2pe" && Args.getLastArgValue(OPT_m) != "arm64pe" && !Args.hasArg(OPT_dynamicbase)) Index: MinGW/Options.td =================================================================== --- MinGW/Options.td +++ MinGW/Options.td @@ -14,6 +14,7 @@ def gc_sections: F<"gc-sections">, HelpText<"Remove unused sections">; def icf: J<"icf=">, HelpText<"Identical code folding">; def image_base: S<"image-base">, HelpText<"Base address of the program">; +def kill_at: F<"kill-at">, HelpText<"Remove @n from exported symbols">; def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"">, HelpText<"Root name of library to use">; def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">; Index: test/COFF/def-export-stdcall.s =================================================================== --- test/COFF/def-export-stdcall.s +++ test/COFF/def-export-stdcall.s @@ -59,6 +59,24 @@ # DECORATED-MINGW-EXPORTS: Name: @fastcall@8 # DECORATED-MINGW-EXPORTS: Name: stdcall@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 + +# MINGW-KILL-AT-EXPORTS: Name: fastcall +# MINGW-KILL-AT-EXPORTS: Name: stdcall + .def _stdcall@8; .scl 2; Index: test/MinGW/driver.test =================================================================== --- test/MinGW/driver.test +++ test/MinGW/driver.test @@ -126,3 +126,7 @@ ICF: -opt:icf RUN: ld.lld -### -m i386pep --start-group foo.o --end-group + +RUN: ld.lld -### foo.o -m i386pe -shared --kill-at | FileCheck -check-prefix=KILL-AT %s +RUN: ld.lld -### foo.o -m i386pe -shared -kill-at | FileCheck -check-prefix=KILL-AT %s +KILL-AT: -kill-at