-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[LLD] [COFF] Fix linking MSVC generated implib header objects #122811
Conversation
@llvm/pr-subscribers-lld-coff @llvm/pr-subscribers-platform-windows Author: Martin Storsjö (mstorsjo) Changesecb5ea6 tried to fix cases when LLD links what seems to be import library header objects from MSVC. However, the fix seems incorrect; the review at https://reviews.llvm.org/D133627 concluded that if this (treating this kind of symbol as a common symbol) is what link.exe does, it's fine. However, this is most probably not what link.exe does. The symbol mentioned in the commit message of ecb5ea6 would be a common symbol with a size of around 3 GB; this is not what might have been intended. That commit tried to avoid running into the error ".idata$4 should not refer to special section 0"; that issue is fixed for a similar style of section symbols in #122806. Therefore, revert ecb5ea6 and extend the fix from #122806 to also work for the section symbols in MSVC generated import libraries. The primary strange thing about them, is that the section symbols have the value 3221225536, 0xC0000040. This value matches the Windows status code STATUS_SECTION_TOO_BIG. If interpreted literally, this value would mean that the symbols refer to an offset of 3 GB after the start of a section. Therefore, this seemingly bogus offset needs to be handled somehow. GNU binutils also does support linking against MSVC generated import libraries - I wonder how they do it. Do they ignore the symbol Value field for symbols of type IMAGE_SYM_CLASS_SECTION? The current hacky solution in this commit is not correct as is though. Finally - for testing, I'm constructing the header/trailer object files from .yaml, but it's hard to construct a full proper import library that way, as the short import library files for the individual symbols can't be synthesized from .yaml yet. (And even if we could do that, it's a bit tricky to build a static library with all members named e.g. "foo.dll".) Full diff: https://github.com/llvm/llvm-project/pull/122811.diff 8 Files Affected:
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index a94c984cfd4870..86284f042fe7a3 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -746,6 +746,26 @@ std::optional<Symbol *> ObjFile::createDefined(
if (sectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
return nullptr;
+ if (sym.isEmptySectionDeclaration()) {
+ // As there is no coff_section in the object file for these, make a
+ // new virtual one, with everything zeroed out (i.e. an empty section),
+ // with only the name and characteristics set.
+ StringRef name = getName();
+ auto *hdr = make<coff_section>();
+ memset(hdr, 0, sizeof(*hdr));
+ strncpy(hdr->Name, name.data(),
+ std::min(name.size(), (size_t)COFF::NameSize));
+ // We have no idea what characteristics should be assumed here; pick
+ // a default. This matches what is used for .idata sections in the regular
+ // object files in import libraries.
+ hdr->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
+ IMAGE_SCN_MEM_WRITE;
+ auto *sc = make<SectionChunk>(this, hdr);
+ chunks.push_back(sc);
+ return make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false,
+ /*IsExternal*/ false, sym.getGeneric(), sc);
+ }
+
if (llvm::COFF::isReservedSectionNumber(sectionNumber))
Fatal(ctx) << toString(this) << ": " << getName()
<< " should not refer to special section "
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index 465d4df52c6300..6e8a9a92283530 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -219,7 +219,9 @@ class DefinedRegular : public DefinedCOFF {
return s->kind() == DefinedRegularKind;
}
- uint64_t getRVA() const { return (*data)->getRVA() + sym->Value; }
+ uint64_t getRVA() const {
+ return (*data)->getRVA() + (sym->Value != 0xC0000040 ? sym->Value : 0);
+ }
SectionChunk *getChunk() const { return *data; }
uint32_t getValue() const { return sym->Value; }
diff --git a/lld/test/COFF/Inputs/msvc-implib1.yaml b/lld/test/COFF/Inputs/msvc-implib1.yaml
new file mode 100644
index 00000000000000..874913b527e406
--- /dev/null
+++ b/lld/test/COFF/Inputs/msvc-implib1.yaml
@@ -0,0 +1,75 @@
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.idata$2'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: '0000000000000000000000000000000000000000'
+ SizeOfRawData: 20
+ Relocations:
+ - VirtualAddress: 12
+ SymbolName: '.idata$6'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 0
+ SymbolName: '.idata$4'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 16
+ SymbolName: '.idata$5'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - Name: '.idata$6'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 2
+ SectionData: 666F6F2E646C6C00
+ SizeOfRawData: 8
+symbols:
+ - Name: '@comp.id'
+ Value: 16877185
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: __IMPORT_DESCRIPTOR_foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '.idata$2'
+ Value: 3221225536
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_SECTION
+ - Name: '.idata$6'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '.idata$4'
+ Value: 3221225536
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_SECTION
+ - Name: '.idata$5'
+ Value: 3221225536
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_SECTION
+ - Name: __NULL_IMPORT_DESCRIPTOR
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: "�foo_NULL_THUNK_DATA"
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/Inputs/msvc-implib2.yaml b/lld/test/COFF/Inputs/msvc-implib2.yaml
new file mode 100644
index 00000000000000..50cb1df842f9cd
--- /dev/null
+++ b/lld/test/COFF/Inputs/msvc-implib2.yaml
@@ -0,0 +1,24 @@
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.idata$3'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: '0000000000000000000000000000000000000000'
+ SizeOfRawData: 20
+symbols:
+ - Name: '@comp.id'
+ Value: 16877185
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: __NULL_IMPORT_DESCRIPTOR
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/Inputs/msvc-implib3.yaml b/lld/test/COFF/Inputs/msvc-implib3.yaml
new file mode 100644
index 00000000000000..2cc78a7048f96e
--- /dev/null
+++ b/lld/test/COFF/Inputs/msvc-implib3.yaml
@@ -0,0 +1,29 @@
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.idata$5'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 8
+ SectionData: '0000000000000000'
+ SizeOfRawData: 8
+ - Name: '.idata$4'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 8
+ SectionData: '0000000000000000'
+ SizeOfRawData: 8
+symbols:
+ - Name: '@comp.id'
+ Value: 16877185
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: "�foo_NULL_THUNK_DATA"
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/wholearchive-implib.s b/lld/test/COFF/wholearchive-implib.s
new file mode 100644
index 00000000000000..4611d778316c42
--- /dev/null
+++ b/lld/test/COFF/wholearchive-implib.s
@@ -0,0 +1,55 @@
+// REQUIRES: x86
+// RUN: split-file %s %t.dir
+// RUN: llvm-lib -machine:amd64 -out:%t.lib -def:%t.dir/lib.def
+// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %t.dir/main.s -o %t.main.obj
+
+// RUN: yaml2obj %S/Inputs/msvc-implib1.yaml -o %t.msvc-implib1.obj
+// RUN: yaml2obj %S/Inputs/msvc-implib2.yaml -o %t.msvc-implib2.obj
+// RUN: yaml2obj %S/Inputs/msvc-implib3.yaml -o %t.msvc-implib3.obj
+// RUN: llvm-lib -out:%t-msvc.lib %t.msvc-implib1.obj %t.msvc-implib2.obj %t.msvc-implib3.obj
+// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %t.dir/main-nocall.s -o %t.main-nocall.obj
+
+// RUN: lld-link -out:%t.exe %t.main.obj -wholearchive:%t.lib -entry:entry -subsystem:console
+// RUN: llvm-readobj --coff-imports %t.exe | FileCheck %s
+
+// RUN: lld-link -out:%t-msvc.exe %t.main-nocall.obj -wholearchive:%t-msvc.lib -entry:entry -subsystem:console
+// RUN: llvm-readobj --coff-imports %t-msvc.exe | FileCheck %s --check-prefix=CHECK-MSVC
+
+// As LLD usually doesn't use the header/trailer object files from import
+// libraries, but instead synthesizes those structures, we end up with two
+// import directory entries if we force those objects to be included.
+
+// CHECK: Import {
+// CHECK-NEXT: Name: lib.dll
+// CHECK-NEXT: ImportLookupTableRVA: 0x2050
+// CHECK-NEXT: ImportAddressTableRVA: 0x2070
+// CHECK-NEXT: }
+// CHECK-NEXT: Import {
+// CHECK-NEXT: Name: lib.dll
+// CHECK-NEXT: ImportLookupTableRVA: 0x2058
+// CHECK-NEXT: ImportAddressTableRVA: 0x2078
+// CHECK-NEXT: Symbol: func (0)
+// CHECK-NEXT: }
+
+// CHECK-MSVC: Import {
+// CHECK-MSVC-NEXT: Name: foo.dll
+// CHECK-MSVC-NEXT: ImportLookupTableRVA: 0x2040
+// CHECK-MSVC-NEXT: ImportAddressTableRVA: 0x2050
+// CHECK-MSVC-NEXT: }
+
+
+#--- main.s
+.global entry
+entry:
+ call func
+ ret
+
+#--- main-nocall.s
+.global entry
+entry:
+ ret
+
+#--- lib.def
+LIBRARY lib.dll
+EXPORTS
+func
diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h
index 05b3587224c296..3d0738c4090497 100644
--- a/llvm/include/llvm/Object/COFF.h
+++ b/llvm/include/llvm/Object/COFF.h
@@ -383,8 +383,8 @@ class COFFSymbolRef {
}
bool isCommon() const {
- return (isExternal() || isSection()) &&
- getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && getValue() != 0;
+ return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
+ getValue() != 0;
}
bool isUndefined() const {
@@ -392,6 +392,10 @@ class COFFSymbolRef {
getValue() == 0;
}
+ bool isEmptySectionDeclaration() const {
+ return isSection() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED;
+ }
+
bool isWeakExternal() const {
return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
}
diff --git a/llvm/test/Object/coff-sec-sym.test b/llvm/test/Object/coff-sec-sym.test
deleted file mode 100644
index 0b7117250150de..00000000000000
--- a/llvm/test/Object/coff-sec-sym.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# Check that section symbol (IMAGE_SYM_CLASS_SECTION) is listed as common symbol.
-
-# RUN: yaml2obj %s -o %t.obj
-# RUN: llvm-nm %t.obj | FileCheck %s
-
-# CHECK: 00000001 C foo
-
---- !COFF
-header:
- Machine: IMAGE_FILE_MACHINE_AMD64
- Characteristics: [ ]
-sections:
-symbols:
- - Name: foo
- Value: 1
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_SECTION
-...
|
@llvm/pr-subscribers-lld Author: Martin Storsjö (mstorsjo) Changesecb5ea6 tried to fix cases when LLD links what seems to be import library header objects from MSVC. However, the fix seems incorrect; the review at https://reviews.llvm.org/D133627 concluded that if this (treating this kind of symbol as a common symbol) is what link.exe does, it's fine. However, this is most probably not what link.exe does. The symbol mentioned in the commit message of ecb5ea6 would be a common symbol with a size of around 3 GB; this is not what might have been intended. That commit tried to avoid running into the error ".idata$4 should not refer to special section 0"; that issue is fixed for a similar style of section symbols in #122806. Therefore, revert ecb5ea6 and extend the fix from #122806 to also work for the section symbols in MSVC generated import libraries. The primary strange thing about them, is that the section symbols have the value 3221225536, 0xC0000040. This value matches the Windows status code STATUS_SECTION_TOO_BIG. If interpreted literally, this value would mean that the symbols refer to an offset of 3 GB after the start of a section. Therefore, this seemingly bogus offset needs to be handled somehow. GNU binutils also does support linking against MSVC generated import libraries - I wonder how they do it. Do they ignore the symbol Value field for symbols of type IMAGE_SYM_CLASS_SECTION? The current hacky solution in this commit is not correct as is though. Finally - for testing, I'm constructing the header/trailer object files from .yaml, but it's hard to construct a full proper import library that way, as the short import library files for the individual symbols can't be synthesized from .yaml yet. (And even if we could do that, it's a bit tricky to build a static library with all members named e.g. "foo.dll".) Full diff: https://github.com/llvm/llvm-project/pull/122811.diff 8 Files Affected:
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index a94c984cfd4870..86284f042fe7a3 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -746,6 +746,26 @@ std::optional<Symbol *> ObjFile::createDefined(
if (sectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
return nullptr;
+ if (sym.isEmptySectionDeclaration()) {
+ // As there is no coff_section in the object file for these, make a
+ // new virtual one, with everything zeroed out (i.e. an empty section),
+ // with only the name and characteristics set.
+ StringRef name = getName();
+ auto *hdr = make<coff_section>();
+ memset(hdr, 0, sizeof(*hdr));
+ strncpy(hdr->Name, name.data(),
+ std::min(name.size(), (size_t)COFF::NameSize));
+ // We have no idea what characteristics should be assumed here; pick
+ // a default. This matches what is used for .idata sections in the regular
+ // object files in import libraries.
+ hdr->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
+ IMAGE_SCN_MEM_WRITE;
+ auto *sc = make<SectionChunk>(this, hdr);
+ chunks.push_back(sc);
+ return make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false,
+ /*IsExternal*/ false, sym.getGeneric(), sc);
+ }
+
if (llvm::COFF::isReservedSectionNumber(sectionNumber))
Fatal(ctx) << toString(this) << ": " << getName()
<< " should not refer to special section "
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index 465d4df52c6300..6e8a9a92283530 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -219,7 +219,9 @@ class DefinedRegular : public DefinedCOFF {
return s->kind() == DefinedRegularKind;
}
- uint64_t getRVA() const { return (*data)->getRVA() + sym->Value; }
+ uint64_t getRVA() const {
+ return (*data)->getRVA() + (sym->Value != 0xC0000040 ? sym->Value : 0);
+ }
SectionChunk *getChunk() const { return *data; }
uint32_t getValue() const { return sym->Value; }
diff --git a/lld/test/COFF/Inputs/msvc-implib1.yaml b/lld/test/COFF/Inputs/msvc-implib1.yaml
new file mode 100644
index 00000000000000..874913b527e406
--- /dev/null
+++ b/lld/test/COFF/Inputs/msvc-implib1.yaml
@@ -0,0 +1,75 @@
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.idata$2'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: '0000000000000000000000000000000000000000'
+ SizeOfRawData: 20
+ Relocations:
+ - VirtualAddress: 12
+ SymbolName: '.idata$6'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 0
+ SymbolName: '.idata$4'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 16
+ SymbolName: '.idata$5'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - Name: '.idata$6'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 2
+ SectionData: 666F6F2E646C6C00
+ SizeOfRawData: 8
+symbols:
+ - Name: '@comp.id'
+ Value: 16877185
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: __IMPORT_DESCRIPTOR_foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '.idata$2'
+ Value: 3221225536
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_SECTION
+ - Name: '.idata$6'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '.idata$4'
+ Value: 3221225536
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_SECTION
+ - Name: '.idata$5'
+ Value: 3221225536
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_SECTION
+ - Name: __NULL_IMPORT_DESCRIPTOR
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: "�foo_NULL_THUNK_DATA"
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/Inputs/msvc-implib2.yaml b/lld/test/COFF/Inputs/msvc-implib2.yaml
new file mode 100644
index 00000000000000..50cb1df842f9cd
--- /dev/null
+++ b/lld/test/COFF/Inputs/msvc-implib2.yaml
@@ -0,0 +1,24 @@
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.idata$3'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: '0000000000000000000000000000000000000000'
+ SizeOfRawData: 20
+symbols:
+ - Name: '@comp.id'
+ Value: 16877185
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: __NULL_IMPORT_DESCRIPTOR
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/Inputs/msvc-implib3.yaml b/lld/test/COFF/Inputs/msvc-implib3.yaml
new file mode 100644
index 00000000000000..2cc78a7048f96e
--- /dev/null
+++ b/lld/test/COFF/Inputs/msvc-implib3.yaml
@@ -0,0 +1,29 @@
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.idata$5'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 8
+ SectionData: '0000000000000000'
+ SizeOfRawData: 8
+ - Name: '.idata$4'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 8
+ SectionData: '0000000000000000'
+ SizeOfRawData: 8
+symbols:
+ - Name: '@comp.id'
+ Value: 16877185
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: "�foo_NULL_THUNK_DATA"
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/wholearchive-implib.s b/lld/test/COFF/wholearchive-implib.s
new file mode 100644
index 00000000000000..4611d778316c42
--- /dev/null
+++ b/lld/test/COFF/wholearchive-implib.s
@@ -0,0 +1,55 @@
+// REQUIRES: x86
+// RUN: split-file %s %t.dir
+// RUN: llvm-lib -machine:amd64 -out:%t.lib -def:%t.dir/lib.def
+// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %t.dir/main.s -o %t.main.obj
+
+// RUN: yaml2obj %S/Inputs/msvc-implib1.yaml -o %t.msvc-implib1.obj
+// RUN: yaml2obj %S/Inputs/msvc-implib2.yaml -o %t.msvc-implib2.obj
+// RUN: yaml2obj %S/Inputs/msvc-implib3.yaml -o %t.msvc-implib3.obj
+// RUN: llvm-lib -out:%t-msvc.lib %t.msvc-implib1.obj %t.msvc-implib2.obj %t.msvc-implib3.obj
+// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %t.dir/main-nocall.s -o %t.main-nocall.obj
+
+// RUN: lld-link -out:%t.exe %t.main.obj -wholearchive:%t.lib -entry:entry -subsystem:console
+// RUN: llvm-readobj --coff-imports %t.exe | FileCheck %s
+
+// RUN: lld-link -out:%t-msvc.exe %t.main-nocall.obj -wholearchive:%t-msvc.lib -entry:entry -subsystem:console
+// RUN: llvm-readobj --coff-imports %t-msvc.exe | FileCheck %s --check-prefix=CHECK-MSVC
+
+// As LLD usually doesn't use the header/trailer object files from import
+// libraries, but instead synthesizes those structures, we end up with two
+// import directory entries if we force those objects to be included.
+
+// CHECK: Import {
+// CHECK-NEXT: Name: lib.dll
+// CHECK-NEXT: ImportLookupTableRVA: 0x2050
+// CHECK-NEXT: ImportAddressTableRVA: 0x2070
+// CHECK-NEXT: }
+// CHECK-NEXT: Import {
+// CHECK-NEXT: Name: lib.dll
+// CHECK-NEXT: ImportLookupTableRVA: 0x2058
+// CHECK-NEXT: ImportAddressTableRVA: 0x2078
+// CHECK-NEXT: Symbol: func (0)
+// CHECK-NEXT: }
+
+// CHECK-MSVC: Import {
+// CHECK-MSVC-NEXT: Name: foo.dll
+// CHECK-MSVC-NEXT: ImportLookupTableRVA: 0x2040
+// CHECK-MSVC-NEXT: ImportAddressTableRVA: 0x2050
+// CHECK-MSVC-NEXT: }
+
+
+#--- main.s
+.global entry
+entry:
+ call func
+ ret
+
+#--- main-nocall.s
+.global entry
+entry:
+ ret
+
+#--- lib.def
+LIBRARY lib.dll
+EXPORTS
+func
diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h
index 05b3587224c296..3d0738c4090497 100644
--- a/llvm/include/llvm/Object/COFF.h
+++ b/llvm/include/llvm/Object/COFF.h
@@ -383,8 +383,8 @@ class COFFSymbolRef {
}
bool isCommon() const {
- return (isExternal() || isSection()) &&
- getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && getValue() != 0;
+ return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
+ getValue() != 0;
}
bool isUndefined() const {
@@ -392,6 +392,10 @@ class COFFSymbolRef {
getValue() == 0;
}
+ bool isEmptySectionDeclaration() const {
+ return isSection() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED;
+ }
+
bool isWeakExternal() const {
return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
}
diff --git a/llvm/test/Object/coff-sec-sym.test b/llvm/test/Object/coff-sec-sym.test
deleted file mode 100644
index 0b7117250150de..00000000000000
--- a/llvm/test/Object/coff-sec-sym.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# Check that section symbol (IMAGE_SYM_CLASS_SECTION) is listed as common symbol.
-
-# RUN: yaml2obj %s -o %t.obj
-# RUN: llvm-nm %t.obj | FileCheck %s
-
-# CHECK: 00000001 C foo
-
---- !COFF
-header:
- Machine: IMAGE_FILE_MACHINE_AMD64
- Characteristics: [ ]
-sections:
-symbols:
- - Name: foo
- Value: 1
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_SECTION
-...
|
@llvm/pr-subscribers-llvm-binary-utilities Author: Martin Storsjö (mstorsjo) Changesecb5ea6 tried to fix cases when LLD links what seems to be import library header objects from MSVC. However, the fix seems incorrect; the review at https://reviews.llvm.org/D133627 concluded that if this (treating this kind of symbol as a common symbol) is what link.exe does, it's fine. However, this is most probably not what link.exe does. The symbol mentioned in the commit message of ecb5ea6 would be a common symbol with a size of around 3 GB; this is not what might have been intended. That commit tried to avoid running into the error ".idata$4 should not refer to special section 0"; that issue is fixed for a similar style of section symbols in #122806. Therefore, revert ecb5ea6 and extend the fix from #122806 to also work for the section symbols in MSVC generated import libraries. The primary strange thing about them, is that the section symbols have the value 3221225536, 0xC0000040. This value matches the Windows status code STATUS_SECTION_TOO_BIG. If interpreted literally, this value would mean that the symbols refer to an offset of 3 GB after the start of a section. Therefore, this seemingly bogus offset needs to be handled somehow. GNU binutils also does support linking against MSVC generated import libraries - I wonder how they do it. Do they ignore the symbol Value field for symbols of type IMAGE_SYM_CLASS_SECTION? The current hacky solution in this commit is not correct as is though. Finally - for testing, I'm constructing the header/trailer object files from .yaml, but it's hard to construct a full proper import library that way, as the short import library files for the individual symbols can't be synthesized from .yaml yet. (And even if we could do that, it's a bit tricky to build a static library with all members named e.g. "foo.dll".) Full diff: https://github.com/llvm/llvm-project/pull/122811.diff 8 Files Affected:
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index a94c984cfd4870..86284f042fe7a3 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -746,6 +746,26 @@ std::optional<Symbol *> ObjFile::createDefined(
if (sectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
return nullptr;
+ if (sym.isEmptySectionDeclaration()) {
+ // As there is no coff_section in the object file for these, make a
+ // new virtual one, with everything zeroed out (i.e. an empty section),
+ // with only the name and characteristics set.
+ StringRef name = getName();
+ auto *hdr = make<coff_section>();
+ memset(hdr, 0, sizeof(*hdr));
+ strncpy(hdr->Name, name.data(),
+ std::min(name.size(), (size_t)COFF::NameSize));
+ // We have no idea what characteristics should be assumed here; pick
+ // a default. This matches what is used for .idata sections in the regular
+ // object files in import libraries.
+ hdr->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
+ IMAGE_SCN_MEM_WRITE;
+ auto *sc = make<SectionChunk>(this, hdr);
+ chunks.push_back(sc);
+ return make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false,
+ /*IsExternal*/ false, sym.getGeneric(), sc);
+ }
+
if (llvm::COFF::isReservedSectionNumber(sectionNumber))
Fatal(ctx) << toString(this) << ": " << getName()
<< " should not refer to special section "
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index 465d4df52c6300..6e8a9a92283530 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -219,7 +219,9 @@ class DefinedRegular : public DefinedCOFF {
return s->kind() == DefinedRegularKind;
}
- uint64_t getRVA() const { return (*data)->getRVA() + sym->Value; }
+ uint64_t getRVA() const {
+ return (*data)->getRVA() + (sym->Value != 0xC0000040 ? sym->Value : 0);
+ }
SectionChunk *getChunk() const { return *data; }
uint32_t getValue() const { return sym->Value; }
diff --git a/lld/test/COFF/Inputs/msvc-implib1.yaml b/lld/test/COFF/Inputs/msvc-implib1.yaml
new file mode 100644
index 00000000000000..874913b527e406
--- /dev/null
+++ b/lld/test/COFF/Inputs/msvc-implib1.yaml
@@ -0,0 +1,75 @@
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.idata$2'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: '0000000000000000000000000000000000000000'
+ SizeOfRawData: 20
+ Relocations:
+ - VirtualAddress: 12
+ SymbolName: '.idata$6'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 0
+ SymbolName: '.idata$4'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 16
+ SymbolName: '.idata$5'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - Name: '.idata$6'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 2
+ SectionData: 666F6F2E646C6C00
+ SizeOfRawData: 8
+symbols:
+ - Name: '@comp.id'
+ Value: 16877185
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: __IMPORT_DESCRIPTOR_foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '.idata$2'
+ Value: 3221225536
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_SECTION
+ - Name: '.idata$6'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '.idata$4'
+ Value: 3221225536
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_SECTION
+ - Name: '.idata$5'
+ Value: 3221225536
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_SECTION
+ - Name: __NULL_IMPORT_DESCRIPTOR
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: "�foo_NULL_THUNK_DATA"
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/Inputs/msvc-implib2.yaml b/lld/test/COFF/Inputs/msvc-implib2.yaml
new file mode 100644
index 00000000000000..50cb1df842f9cd
--- /dev/null
+++ b/lld/test/COFF/Inputs/msvc-implib2.yaml
@@ -0,0 +1,24 @@
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.idata$3'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: '0000000000000000000000000000000000000000'
+ SizeOfRawData: 20
+symbols:
+ - Name: '@comp.id'
+ Value: 16877185
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: __NULL_IMPORT_DESCRIPTOR
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/Inputs/msvc-implib3.yaml b/lld/test/COFF/Inputs/msvc-implib3.yaml
new file mode 100644
index 00000000000000..2cc78a7048f96e
--- /dev/null
+++ b/lld/test/COFF/Inputs/msvc-implib3.yaml
@@ -0,0 +1,29 @@
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.idata$5'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 8
+ SectionData: '0000000000000000'
+ SizeOfRawData: 8
+ - Name: '.idata$4'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 8
+ SectionData: '0000000000000000'
+ SizeOfRawData: 8
+symbols:
+ - Name: '@comp.id'
+ Value: 16877185
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: "�foo_NULL_THUNK_DATA"
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/wholearchive-implib.s b/lld/test/COFF/wholearchive-implib.s
new file mode 100644
index 00000000000000..4611d778316c42
--- /dev/null
+++ b/lld/test/COFF/wholearchive-implib.s
@@ -0,0 +1,55 @@
+// REQUIRES: x86
+// RUN: split-file %s %t.dir
+// RUN: llvm-lib -machine:amd64 -out:%t.lib -def:%t.dir/lib.def
+// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %t.dir/main.s -o %t.main.obj
+
+// RUN: yaml2obj %S/Inputs/msvc-implib1.yaml -o %t.msvc-implib1.obj
+// RUN: yaml2obj %S/Inputs/msvc-implib2.yaml -o %t.msvc-implib2.obj
+// RUN: yaml2obj %S/Inputs/msvc-implib3.yaml -o %t.msvc-implib3.obj
+// RUN: llvm-lib -out:%t-msvc.lib %t.msvc-implib1.obj %t.msvc-implib2.obj %t.msvc-implib3.obj
+// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %t.dir/main-nocall.s -o %t.main-nocall.obj
+
+// RUN: lld-link -out:%t.exe %t.main.obj -wholearchive:%t.lib -entry:entry -subsystem:console
+// RUN: llvm-readobj --coff-imports %t.exe | FileCheck %s
+
+// RUN: lld-link -out:%t-msvc.exe %t.main-nocall.obj -wholearchive:%t-msvc.lib -entry:entry -subsystem:console
+// RUN: llvm-readobj --coff-imports %t-msvc.exe | FileCheck %s --check-prefix=CHECK-MSVC
+
+// As LLD usually doesn't use the header/trailer object files from import
+// libraries, but instead synthesizes those structures, we end up with two
+// import directory entries if we force those objects to be included.
+
+// CHECK: Import {
+// CHECK-NEXT: Name: lib.dll
+// CHECK-NEXT: ImportLookupTableRVA: 0x2050
+// CHECK-NEXT: ImportAddressTableRVA: 0x2070
+// CHECK-NEXT: }
+// CHECK-NEXT: Import {
+// CHECK-NEXT: Name: lib.dll
+// CHECK-NEXT: ImportLookupTableRVA: 0x2058
+// CHECK-NEXT: ImportAddressTableRVA: 0x2078
+// CHECK-NEXT: Symbol: func (0)
+// CHECK-NEXT: }
+
+// CHECK-MSVC: Import {
+// CHECK-MSVC-NEXT: Name: foo.dll
+// CHECK-MSVC-NEXT: ImportLookupTableRVA: 0x2040
+// CHECK-MSVC-NEXT: ImportAddressTableRVA: 0x2050
+// CHECK-MSVC-NEXT: }
+
+
+#--- main.s
+.global entry
+entry:
+ call func
+ ret
+
+#--- main-nocall.s
+.global entry
+entry:
+ ret
+
+#--- lib.def
+LIBRARY lib.dll
+EXPORTS
+func
diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h
index 05b3587224c296..3d0738c4090497 100644
--- a/llvm/include/llvm/Object/COFF.h
+++ b/llvm/include/llvm/Object/COFF.h
@@ -383,8 +383,8 @@ class COFFSymbolRef {
}
bool isCommon() const {
- return (isExternal() || isSection()) &&
- getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && getValue() != 0;
+ return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
+ getValue() != 0;
}
bool isUndefined() const {
@@ -392,6 +392,10 @@ class COFFSymbolRef {
getValue() == 0;
}
+ bool isEmptySectionDeclaration() const {
+ return isSection() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED;
+ }
+
bool isWeakExternal() const {
return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
}
diff --git a/llvm/test/Object/coff-sec-sym.test b/llvm/test/Object/coff-sec-sym.test
deleted file mode 100644
index 0b7117250150de..00000000000000
--- a/llvm/test/Object/coff-sec-sym.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# Check that section symbol (IMAGE_SYM_CLASS_SECTION) is listed as common symbol.
-
-# RUN: yaml2obj %s -o %t.obj
-# RUN: llvm-nm %t.obj | FileCheck %s
-
-# CHECK: 00000001 C foo
-
---- !COFF
-header:
- Machine: IMAGE_FILE_MACHINE_AMD64
- Characteristics: [ ]
-sections:
-symbols:
- - Name: foo
- Value: 1
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_SECTION
-...
|
Thanks for the patch, @mstorsjo! Even though I am not sure how MSVC or GNU binutils handles this, but your patch looks reasonable to me. |
lld/COFF/Symbols.h
Outdated
@@ -219,7 +219,9 @@ class DefinedRegular : public DefinedCOFF { | |||
return s->kind() == DefinedRegularKind; | |||
} | |||
|
|||
uint64_t getRVA() const { return (*data)->getRVA() + sym->Value; } | |||
uint64_t getRVA() const { | |||
return (*data)->getRVA() + (sym->Value != 0xC0000040 ? sym->Value : 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we could avoid special-casing that value. From what I can see with binutils, value is simply ignored for such symbols. Maybe we could just always create a symbol with 0 value when handling isEmptySectionDeclaration
in lld-link.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we most probably should avoid hardcoding it, especially like this; this was my mildly provocative PoC to show where/how we may need to work around it :-)
Indeed, ignoring the offset when handling isEmptySectionDeclaration
probably is good, but that's apparently not entirely enough either. Note this section symbol:
- Name: '.idata$2'
Value: 3221225536
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_SECTION
So apparently we should ignore the Value
entirely, for any section type symbol it seems? I haven't quite yet had time to work out the logic around this, how binutils and link.exe operate around this.
A couple more observations about the MSVC behaviour here. I used inputs like this: #--- main.yaml
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
sections:
- Name: '.itest$2'
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
Alignment: 4
SectionData: '00000000000000000000'
SizeOfRawData: 10
Relocations:
- VirtualAddress: 0
SymbolName: '.itest$6'
Type: IMAGE_REL_AMD64_ADDR32NB
- Name: '.itest$6'
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
Alignment: 2
SectionData: 01000000
SizeOfRawData: 4
symbols:
- Name: '.itest$2'
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_SECTION
- Name: '.itest$6'
Value: 3221225536
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_SECTION
- Name: '.itest$4'
Value: 3221225536
SectionNumber: 0
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_SECTION
...
#--- sect-def.yaml
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
sections:
- Name: '.itest$4'
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
Alignment: 2
SectionData: 'ffff'
SizeOfRawData: 2
symbols:
- Name: '.itest$4'
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_SECTION
... Compared with earlier tests, I'm adding a second yaml object for the actual
For the former issue, I'm not sure if there's much of an action we need to take; it is very distracting when trying to figure out how things really work, but I'm not sure if resolving this is relevant for this case. For the latter issue, we should at least ignore the Should we add a |
02789ac
to
4668992
Compare
Interesting findings, thanks!
Agreed, sounds doesn't sounds like something we need to worry about.
I guess instead of a flag, |
I made an attempt at this now, but adding a Or should we create a synthetic |
Oh, that sounds like a good idea. That does increase the size of |
4668992
to
dc495a0
Compare
This approach seems quite straightforward, and doesn't require adjusting the existing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks reasonable to me.
dc495a0
to
8765e26
Compare
lld/test/COFF/wholearchive-implib.s
Outdated
@@ -3,9 +3,18 @@ | |||
// RUN: llvm-lib -machine:amd64 -out:%t.lib -def:%t.dir/lib.def | |||
// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %t.dir/main.s -o %t.main.obj | |||
|
|||
// RUN: yaml2obj %S/Inputs/msvc-implib1.yaml -o %t.msvc-implib1.obj |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw, I wonder if we really need these extra tests (they're kinda ugly with three separate .yaml files) - I think the changes in empty-section-decl.yaml
are enough to cover the changes in this PR, so I could drop the rest of the added tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
empty-section-decl.yaml
changes seem enough to me as well.
ecb5ea6 tried to fix cases when LLD links what seems to be import library header objects from MSVC. However, the fix seems incorrect; the review at https://reviews.llvm.org/D133627 concluded that if this (treating this kind of symbol as a common symbol) is what link.exe does, it's fine. However, this is most probably not what link.exe does. The symbol mentioned in the commit message of ecb5ea6 would be a common symbol with a size of around 3 GB; this is not what might have been intended. That commit tried to avoid running into the error ".idata$4 should not refer to special section 0"; that issue is fixed for a similar style of section symbols in 4a4a8a1. Therefore, revert ecb5ea6 and extend the fix from 4a4a8a1 to also work for the section symbols in MSVC generated import libraries. The main detail about them, is that for symbols of type IMAGE_SYM_CLASS_SECTION, the Value field is not an offset, but it is an optional set of flags, corresponding to the Characteristics of the section header (although it may be empty).
8765e26
to
10c9ebe
Compare
COFF/empty-section-decl.yaml started failing on some buildbots (https://lab.llvm.org/buildbot/#/builders/52/builds/5421). Could you please take a look to check if this is related? |
The buildbot is missing some of the test output, but I re-ran the buildbot locally:
|
We are also seeing the same test failure on our internal ASAN builder on Windows. |
#123877) Reverts #122811 due to buildbot breakage e.g., https://lab.llvm.org/buildbot/#/builders/52/builds/5421/steps/11/logs/stdio ASan output from local re-run: ``` ==2780289==ERROR: AddressSanitizer: use-after-poison on address 0x7e0b87e28d28 at pc 0x55a979a99e7e bp 0x7ffe4b18f0b0 sp 0x7ffe4b18f0a8 READ of size 1 at 0x7e0b87e28d28 thread T0 #0 0x55a979a99e7d in getStorageClass /usr/local/google/home/thurston/buildbot_repro/llvm-project/llvm/include/llvm/Object/COFF.h:344 #1 0x55a979a99e7d in isSectionDefinition /usr/local/google/home/thurston/buildbot_repro/llvm-project/llvm/include/llvm/Object/COFF.h:429:9 #2 0x55a979a99e7d in getSymbols /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/LLDMapFile.cpp:54:42 #3 0x55a979a99e7d in lld::coff::writeLLDMapFile(lld::coff::COFFLinkerContext const&) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/LLDMapFile.cpp:103:40 #4 0x55a979a16879 in (anonymous namespace)::Writer::run() /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/Writer.cpp:810:3 #5 0x55a979a00aac in lld::coff::writeResult(lld::coff::COFFLinkerContext&) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/Writer.cpp:354:15 #6 0x55a97985f7ed in lld::coff::LinkerDriver::linkerMain(llvm::ArrayRef<char const*>) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/Driver.cpp:2826:3 #7 0x55a97984cdd3 in lld::coff::link(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, bool, bool) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/Driver.cpp:97:15 #8 0x55a9797f9793 in lld::unsafeLldMain(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, llvm::ArrayRef<lld::DriverDef>, bool) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/Common/DriverDispatcher.cpp:163:12 #9 0x55a9797fa3b6 in operator() /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/Common/DriverDispatcher.cpp:188:15 #10 0x55a9797fa3b6 in void llvm::function_ref<void ()>::callback_fn<lld::lldMain(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, llvm::ArrayRef<lld::DriverDef>)::$_0>(long) /usr/local/google/home/thurston/buildbot_repro/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:12 #11 0x55a97966cb93 in operator() /usr/local/google/home/thurston/buildbot_repro/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:12 #12 0x55a97966cb93 in llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) /usr/local/google/home/thurston/buildbot_repro/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:426:3 #13 0x55a9797f9dc3 in lld::lldMain(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, llvm::ArrayRef<lld::DriverDef>) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/Common/DriverDispatcher.cpp:187:14 #14 0x55a979627512 in lld_main(int, char**, llvm::ToolContext const&) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/tools/lld/lld.cpp:103:14 #15 0x55a979628731 in main /usr/local/google/home/thurston/buildbot_repro/llvm_build_asan/tools/lld/tools/lld/lld-driver.cpp:17:10 #16 0x7ffb8b202c89 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #17 0x7ffb8b202d44 in __libc_start_main csu/../csu/libc-start.c:360:3 #18 0x55a97953ef60 in _start (/usr/local/google/home/thurston/buildbot_repro/llvm_build_asan/bin/lld+0x8fd1f60) ```
…der objects" (#123877) Reverts llvm/llvm-project#122811 due to buildbot breakage e.g., https://lab.llvm.org/buildbot/#/builders/52/builds/5421/steps/11/logs/stdio ASan output from local re-run: ``` ==2780289==ERROR: AddressSanitizer: use-after-poison on address 0x7e0b87e28d28 at pc 0x55a979a99e7e bp 0x7ffe4b18f0b0 sp 0x7ffe4b18f0a8 READ of size 1 at 0x7e0b87e28d28 thread T0 #0 0x55a979a99e7d in getStorageClass /usr/local/google/home/thurston/buildbot_repro/llvm-project/llvm/include/llvm/Object/COFF.h:344 #1 0x55a979a99e7d in isSectionDefinition /usr/local/google/home/thurston/buildbot_repro/llvm-project/llvm/include/llvm/Object/COFF.h:429:9 #2 0x55a979a99e7d in getSymbols /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/LLDMapFile.cpp:54:42 #3 0x55a979a99e7d in lld::coff::writeLLDMapFile(lld::coff::COFFLinkerContext const&) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/LLDMapFile.cpp:103:40 #4 0x55a979a16879 in (anonymous namespace)::Writer::run() /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/Writer.cpp:810:3 #5 0x55a979a00aac in lld::coff::writeResult(lld::coff::COFFLinkerContext&) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/Writer.cpp:354:15 #6 0x55a97985f7ed in lld::coff::LinkerDriver::linkerMain(llvm::ArrayRef<char const*>) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/Driver.cpp:2826:3 #7 0x55a97984cdd3 in lld::coff::link(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, bool, bool) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/COFF/Driver.cpp:97:15 #8 0x55a9797f9793 in lld::unsafeLldMain(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, llvm::ArrayRef<lld::DriverDef>, bool) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/Common/DriverDispatcher.cpp:163:12 #9 0x55a9797fa3b6 in operator() /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/Common/DriverDispatcher.cpp:188:15 #10 0x55a9797fa3b6 in void llvm::function_ref<void ()>::callback_fn<lld::lldMain(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, llvm::ArrayRef<lld::DriverDef>)::$_0>(long) /usr/local/google/home/thurston/buildbot_repro/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:12 #11 0x55a97966cb93 in operator() /usr/local/google/home/thurston/buildbot_repro/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:12 #12 0x55a97966cb93 in llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) /usr/local/google/home/thurston/buildbot_repro/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:426:3 #13 0x55a9797f9dc3 in lld::lldMain(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, llvm::ArrayRef<lld::DriverDef>) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/Common/DriverDispatcher.cpp:187:14 #14 0x55a979627512 in lld_main(int, char**, llvm::ToolContext const&) /usr/local/google/home/thurston/buildbot_repro/llvm-project/lld/tools/lld/lld.cpp:103:14 #15 0x55a979628731 in main /usr/local/google/home/thurston/buildbot_repro/llvm_build_asan/tools/lld/tools/lld/lld-driver.cpp:17:10 #16 0x7ffb8b202c89 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #17 0x7ffb8b202d44 in __libc_start_main csu/../csu/libc-start.c:360:3 #18 0x55a97953ef60 in _start (/usr/local/google/home/thurston/buildbot_repro/llvm_build_asan/bin/lld+0x8fd1f60) ```
Sorry about this, and thanks for doing the revert! I'll look into the issue. |
ecb5ea6 tried to fix cases when LLD links what seems to be import library header objects from MSVC. However, the fix seems incorrect; the review at https://reviews.llvm.org/D133627 concluded that if this (treating this kind of symbol as a common symbol) is what link.exe does, it's fine. However, this is most probably not what link.exe does. The symbol mentioned in the commit message of ecb5ea6 would be a common symbol with a size of around 3 GB; this is not what might have been intended. That commit tried to avoid running into the error ".idata$4 should not refer to special section 0"; that issue is fixed for a similar style of section symbols in 4a4a8a1. Therefore, revert ecb5ea6 and extend the fix from 4a4a8a1 to also work for the section symbols in MSVC generated import libraries. The main detail about them, is that for symbols of type IMAGE_SYM_CLASS_SECTION, the Value field is not an offset, but it is an optional set of flags, corresponding to the Characteristics of the section header (although it may be empty). This is a reland of a previous version of this commit, earlier merged in 9457418 / llvm#122811. The previous version failed tests when run with address sanitizer. The issue was that the synthesized coff_symbol_generic object actually will be used to access a full coff_symbol16 or coff_symbol32 struct, see DefinedCOFF::getCOFFSymbol. Therefore, we need to make a copy of the full size of either of them.
ecb5ea6 tried to fix cases when LLD links what seems to be import library header objects from MSVC. However, the fix seems incorrect; the review at https://reviews.llvm.org/D133627 concluded that if this (treating this kind of symbol as a common symbol) is what link.exe does, it's fine. However, this is most probably not what link.exe does. The symbol mentioned in the commit message of ecb5ea6 would be a common symbol with a size of around 3 GB; this is not what might have been intended. That commit tried to avoid running into the error ".idata$4 should not refer to special section 0"; that issue is fixed for a similar style of section symbols in 4a4a8a1. Therefore, revert ecb5ea6 and extend the fix from 4a4a8a1 to also work for the section symbols in MSVC generated import libraries. The main detail about them, is that for symbols of type IMAGE_SYM_CLASS_SECTION, the Value field is not an offset, but it is an optional set of flags, corresponding to the Characteristics of the section header (although it may be empty). This is a reland of a previous version of this commit, earlier merged in 9457418 / llvm#122811. The previous version failed tests when run with address sanitizer. The issue was that the synthesized coff_symbol_generic object actually will be used to access a full coff_symbol16 or coff_symbol32 struct, see DefinedCOFF::getCOFFSymbol. Therefore, we need to make a copy of the full size of either of them.
…123916) ecb5ea6 tried to fix cases when LLD links what seems to be import library header objects from MSVC. However, the fix seems incorrect; the review at https://reviews.llvm.org/D133627 concluded that if this (treating this kind of symbol as a common symbol) is what link.exe does, it's fine. However, this is most probably not what link.exe does. The symbol mentioned in the commit message of ecb5ea6 would be a common symbol with a size of around 3 GB; this is not what might have been intended. That commit tried to avoid running into the error ".idata$4 should not refer to special section 0"; that issue is fixed for a similar style of section symbols in 4a4a8a1. Therefore, revert ecb5ea6 and extend the fix from 4a4a8a1 to also work for the section symbols in MSVC generated import libraries. The main detail about them, is that for symbols of type IMAGE_SYM_CLASS_SECTION, the Value field is not an offset, but it is an optional set of flags, corresponding to the Characteristics of the section header (although it may be empty). This is a reland of a previous version of this commit, earlier merged in 9457418 / #122811. The previous version failed tests when run with address sanitizer. The issue was that the synthesized coff_symbol_generic object actually will be used to access a full coff_symbol16 or coff_symbol32 struct, see DefinedCOFF::getCOFFSymbol. Therefore, we need to make a copy of the full size of either of them.
ecb5ea6 tried to fix cases when LLD links what seems to be import library header objects from MSVC. However, the fix seems incorrect; the review at https://reviews.llvm.org/D133627 concluded that if this (treating this kind of symbol as a common symbol) is what link.exe does, it's fine.
However, this is most probably not what link.exe does. The symbol mentioned in the commit message of ecb5ea6 would be a common symbol with a size of around 3 GB; this is not what might have been intended.
That commit tried to avoid running into the error ".idata$4 should not refer to special section 0"; that issue is fixed for a similar style of section symbols in 4a4a8a1.
Therefore, revert ecb5ea6 and extend the fix from 4a4a8a1 to also work for the section symbols in MSVC generated import libraries.
The main detail about them, is that for symbols of type IMAGE_SYM_CLASS_SECTION, the Value field is not an offset, but it is an optional set of flags, corresponding to the Characteristics of the section header (although it may be empty).