Skip to content

Commit 6575a1f

Browse files
committed
Reland [LLD] [COFF] Fix linking MSVC generated implib header objects
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.
1 parent 7bb949e commit 6575a1f

File tree

4 files changed

+46
-37
lines changed

4 files changed

+46
-37
lines changed

lld/COFF/InputFiles.cpp

+35-8
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ static bool ignoredSymbolName(StringRef name) {
105105
return name == "@feat.00" || name == "@comp.id";
106106
}
107107

108+
static coff_symbol_generic *cloneSymbol(COFFSymbolRef sym) {
109+
if (sym.isBigObj()) {
110+
auto *copy = make<coff_symbol32>(
111+
*reinterpret_cast<const coff_symbol32 *>(sym.getRawPtr()));
112+
return reinterpret_cast<coff_symbol_generic *>(copy);
113+
} else {
114+
auto *copy = make<coff_symbol16>(
115+
*reinterpret_cast<const coff_symbol16 *>(sym.getRawPtr()));
116+
return reinterpret_cast<coff_symbol_generic *>(copy);
117+
}
118+
}
119+
108120
ArchiveFile::ArchiveFile(COFFLinkerContext &ctx, MemoryBufferRef m)
109121
: InputFile(ctx.symtab, ArchiveKind, m) {}
110122

@@ -458,9 +470,16 @@ Symbol *ObjFile::createRegular(COFFSymbolRef sym) {
458470
return nullptr;
459471
return symtab.addUndefined(name, this, false);
460472
}
461-
if (sc)
473+
if (sc) {
474+
const coff_symbol_generic *symGen = sym.getGeneric();
475+
if (sym.isSection()) {
476+
auto *customSymGen = cloneSymbol(sym);
477+
customSymGen->Value = 0;
478+
symGen = customSymGen;
479+
}
462480
return make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false,
463-
/*IsExternal*/ false, sym.getGeneric(), sc);
481+
/*IsExternal*/ false, symGen, sc);
482+
}
464483
return nullptr;
465484
}
466485

@@ -755,15 +774,23 @@ std::optional<Symbol *> ObjFile::createDefined(
755774
memset(hdr, 0, sizeof(*hdr));
756775
strncpy(hdr->Name, name.data(),
757776
std::min(name.size(), (size_t)COFF::NameSize));
758-
// We have no idea what characteristics should be assumed here; pick
759-
// a default. This matches what is used for .idata sections in the regular
760-
// object files in import libraries.
761-
hdr->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
762-
IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_4BYTES;
777+
// The Value field in a section symbol may contain the characteristics,
778+
// or it may be zero, where we make something up (that matches what is
779+
// used in .idata sections in the regular object files in import libraries).
780+
if (sym.getValue())
781+
hdr->Characteristics = sym.getValue() | IMAGE_SCN_ALIGN_4BYTES;
782+
else
783+
hdr->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA |
784+
IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE |
785+
IMAGE_SCN_ALIGN_4BYTES;
763786
auto *sc = make<SectionChunk>(this, hdr);
764787
chunks.push_back(sc);
788+
789+
auto *symGen = cloneSymbol(sym);
790+
// Ignore the Value offset of these symbols, as it may be a bitmask.
791+
symGen->Value = 0;
765792
return make<DefinedRegular>(this, /*name=*/"", /*isCOMDAT=*/false,
766-
/*isExternal=*/false, sym.getGeneric(), sc);
793+
/*isExternal=*/false, symGen, sc);
767794
}
768795

769796
if (llvm::COFF::isReservedSectionNumber(sectionNumber))

lld/test/COFF/empty-section-decl.yaml

+8-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# RUN: FileCheck %s --check-prefix=MAP < %t.map
77

88
# CHECK: Contents of section .itest:
9-
# CHECK-NEXT: 180001000 0c100080 01000000 00000000 01000000
9+
# CHECK-NEXT: 180001000 0c100000 0c100000 00000000 01000000
1010

1111
# MAP: 00001000 0000000a 4 {{.*}}:(.itest$2)
1212
# MAP: 00001000 00000000 0 .itest$2
@@ -28,7 +28,10 @@ sections:
2828
Relocations:
2929
- VirtualAddress: 0
3030
SymbolName: '.itest$4'
31-
Type: IMAGE_REL_AMD64_ADDR64
31+
Type: IMAGE_REL_AMD64_ADDR32NB
32+
- VirtualAddress: 4
33+
SymbolName: '.itest$6'
34+
Type: IMAGE_REL_AMD64_ADDR32NB
3235
- Name: '.itest$6'
3336
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
3437
Alignment: 2
@@ -42,13 +45,13 @@ symbols:
4245
ComplexType: IMAGE_SYM_DTYPE_NULL
4346
StorageClass: IMAGE_SYM_CLASS_SECTION
4447
- Name: '.itest$6'
45-
Value: 0
48+
Value: 3221225536
4649
SectionNumber: 2
4750
SimpleType: IMAGE_SYM_TYPE_NULL
4851
ComplexType: IMAGE_SYM_DTYPE_NULL
49-
StorageClass: IMAGE_SYM_CLASS_STATIC
52+
StorageClass: IMAGE_SYM_CLASS_SECTION
5053
- Name: '.itest$4'
51-
Value: 0
54+
Value: 3221225536
5255
SectionNumber: 0
5356
SimpleType: IMAGE_SYM_TYPE_NULL
5457
ComplexType: IMAGE_SYM_DTYPE_NULL

llvm/include/llvm/Object/COFF.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,8 @@ class COFFSymbolRef {
383383
}
384384

385385
bool isCommon() const {
386-
return (isExternal() || isSection()) &&
387-
getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && getValue() != 0;
386+
return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
387+
getValue() != 0;
388388
}
389389

390390
bool isUndefined() const {
@@ -393,8 +393,7 @@ class COFFSymbolRef {
393393
}
394394

395395
bool isEmptySectionDeclaration() const {
396-
return isSection() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
397-
getValue() == 0;
396+
return isSection() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED;
398397
}
399398

400399
bool isWeakExternal() const {

llvm/test/Object/coff-sec-sym.test

-20
This file was deleted.

0 commit comments

Comments
 (0)