forked from OSchip/llvm-project
[COFF] Improve correctness of def parsing for GNU features
The operator == used for exporting a function with a different name in the DLL compared to the name in the import library (which is useful for adding linker level aliases for function in the import library) is a feature distinct and different from the operator = used for exporting a function with a different name (both in import library and DLL) than in the implementation producing the DLL. When creating an import library using dlltool, from a def file that contains forwards (Func = OtherDll.Func), this shouldn't affect the produced import library, which should still behave just as if it was a normal exported function. This clears a lot of confusion and subtle misunderstandings, and avoids a parameter that was used to avoid creating weak aliases when invoked from lld. (This parameter was added previously due to the existing conflation of the two features.) Differential Revision: https://reviews.llvm.org/D46245 llvm-svn: 331859
This commit is contained in:
parent
f1f8f4a1fd
commit
284ab80f8d
|
@ -74,6 +74,7 @@ struct COFFShortExport {
|
|||
std::string Name;
|
||||
std::string ExtName;
|
||||
std::string SymbolName;
|
||||
std::string AliasTarget;
|
||||
|
||||
uint16_t Ordinal = 0;
|
||||
bool Noname = false;
|
||||
|
@ -81,10 +82,6 @@ struct COFFShortExport {
|
|||
bool Private = false;
|
||||
bool Constant = false;
|
||||
|
||||
bool isWeak() {
|
||||
return ExtName.size() && ExtName != Name;
|
||||
}
|
||||
|
||||
friend bool operator==(const COFFShortExport &L, const COFFShortExport &R) {
|
||||
return L.Name == R.Name && L.ExtName == R.ExtName &&
|
||||
L.Ordinal == R.Ordinal && L.Noname == R.Noname &&
|
||||
|
@ -98,8 +95,7 @@ struct COFFShortExport {
|
|||
|
||||
Error writeImportLibrary(StringRef ImportName, StringRef Path,
|
||||
ArrayRef<COFFShortExport> Exports,
|
||||
COFF::MachineTypes Machine, bool MakeWeakAliases,
|
||||
bool MinGW);
|
||||
COFF::MachineTypes Machine, bool MinGW);
|
||||
|
||||
} // namespace object
|
||||
} // namespace llvm
|
||||
|
|
|
@ -566,8 +566,7 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
|
|||
|
||||
Error writeImportLibrary(StringRef ImportName, StringRef Path,
|
||||
ArrayRef<COFFShortExport> Exports,
|
||||
MachineTypes Machine, bool MakeWeakAliases,
|
||||
bool MinGW) {
|
||||
MachineTypes Machine, bool MinGW) {
|
||||
|
||||
std::vector<NewArchiveMember> Members;
|
||||
ObjectFactory OF(llvm::sys::path::filename(ImportName), Machine);
|
||||
|
@ -585,12 +584,6 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,
|
|||
if (E.Private)
|
||||
continue;
|
||||
|
||||
if (E.isWeak() && MakeWeakAliases) {
|
||||
Members.push_back(OF.createWeakExternal(E.Name, E.ExtName, false));
|
||||
Members.push_back(OF.createWeakExternal(E.Name, E.ExtName, true));
|
||||
continue;
|
||||
}
|
||||
|
||||
ImportType ImportType = IMPORT_CODE;
|
||||
if (E.Data)
|
||||
ImportType = IMPORT_DATA;
|
||||
|
@ -606,6 +599,12 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,
|
|||
if (!Name)
|
||||
return Name.takeError();
|
||||
|
||||
if (!E.AliasTarget.empty() && *Name != E.AliasTarget) {
|
||||
Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, false));
|
||||
Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, true));
|
||||
continue;
|
||||
}
|
||||
|
||||
Members.push_back(
|
||||
OF.createShortImport(*Name, E.Ordinal, ImportType, NameType));
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ enum Kind {
|
|||
Identifier,
|
||||
Comma,
|
||||
Equal,
|
||||
EqualEqual,
|
||||
KwBase,
|
||||
KwConstant,
|
||||
KwData,
|
||||
|
@ -104,9 +105,10 @@ public:
|
|||
}
|
||||
case '=':
|
||||
Buf = Buf.drop_front();
|
||||
// GNU dlltool accepts both = and ==.
|
||||
if (Buf.startswith("="))
|
||||
if (Buf.startswith("=")) {
|
||||
Buf = Buf.drop_front();
|
||||
return Token(EqualEqual, "==");
|
||||
}
|
||||
return Token(Equal, "=");
|
||||
case ',':
|
||||
Buf = Buf.drop_front();
|
||||
|
@ -282,6 +284,13 @@ private:
|
|||
E.Private = true;
|
||||
continue;
|
||||
}
|
||||
if (Tok.K == EqualEqual) {
|
||||
read();
|
||||
E.AliasTarget = Tok.Value;
|
||||
if (Machine == IMAGE_FILE_MACHINE_I386 && !isDecorated(E.AliasTarget, MingwDef))
|
||||
E.AliasTarget = std::string("_").append(E.AliasTarget);
|
||||
continue;
|
||||
}
|
||||
unget();
|
||||
Info.Exports.push_back(E);
|
||||
return Error::success();
|
||||
|
|
|
@ -158,7 +158,7 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
|
|||
|
||||
if (Machine == IMAGE_FILE_MACHINE_I386 && Args.getLastArg(OPT_k)) {
|
||||
for (COFFShortExport& E : Def->Exports) {
|
||||
if (E.isWeak() || (!E.Name.empty() && E.Name[0] == '?'))
|
||||
if (!E.AliasTarget.empty() || (!E.Name.empty() && E.Name[0] == '?'))
|
||||
continue;
|
||||
E.SymbolName = E.Name;
|
||||
// Trim off the trailing decoration. Symbols will always have a
|
||||
|
@ -173,7 +173,7 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
|
|||
}
|
||||
}
|
||||
|
||||
if (writeImportLibrary(Def->OutputFile, Path, Def->Exports, Machine, true, true))
|
||||
if (writeImportLibrary(Def->OutputFile, Path, Def->Exports, Machine, true))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ EXPORTS
|
|||
CdeclFunction
|
||||
StdcallFunction@4
|
||||
@FastcallFunction@4
|
||||
StdcallAlias@4=StdcallFunction@4
|
||||
StdcallAlias@4==StdcallFunction@4
|
||||
??_7exception@@6B@
|
||||
|
||||
; CHECK: Name type: noprefix
|
||||
|
|
|
@ -4,8 +4,25 @@
|
|||
LIBRARY test.dll
|
||||
EXPORTS
|
||||
TestFunction==AltTestFunction
|
||||
; When creating an import library, the DLL internal function name of
|
||||
; the implementation of a function isn't visible at all.
|
||||
ImpLibName = Implementation
|
||||
; A different import library name and implementation name can be mixed
|
||||
; with exposing it via a different name in the DLL than in code.
|
||||
ImpLibName2 = Implementation2 == AltTestFunction2
|
||||
; The fact that a DLL export entry is a forward to a different DLL doesn't
|
||||
; matter for the import library
|
||||
ImpLibName3 = kernel32.Sleep
|
||||
|
||||
; CHECK: U AltTestFunction
|
||||
; CHECK-NEXT: w TestFunction
|
||||
; CHECK: U __imp_AltTestFunction
|
||||
; CHECK-NEXT: w __imp_TestFunction
|
||||
; CHECK: T ImpLibName
|
||||
; CHECK-NEXT: T __imp_ImpLibName
|
||||
; CHECK: U AltTestFunction2
|
||||
; CHECK-NEXT: w ImpLibName2
|
||||
; CHECK: U __imp_AltTestFunction2
|
||||
; CHECK-NEXT: w __imp_ImpLibName2
|
||||
; CHECK: T ImpLibName3
|
||||
; CHECK-NEXT: T __imp_ImpLibName3
|
||||
|
|
Loading…
Reference in New Issue