mirror of
https://github.com/intel/llvm.git
synced 2026-01-17 23:45:25 +08:00
Reland [LLD] [COFF] Fix linking MSVC generated implib header objects (#123916)
ecb5ea6a26tried 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 ofecb5ea6a26would 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 in4a4a8a1476. Therefore, revertecb5ea6a26and extend the fix from4a4a8a1476to 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 in9457418e66/ #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.
This commit is contained in:
@@ -105,6 +105,18 @@ static bool ignoredSymbolName(StringRef name) {
|
||||
return name == "@feat.00" || name == "@comp.id";
|
||||
}
|
||||
|
||||
static coff_symbol_generic *cloneSymbol(COFFSymbolRef sym) {
|
||||
if (sym.isBigObj()) {
|
||||
auto *copy = make<coff_symbol32>(
|
||||
*reinterpret_cast<const coff_symbol32 *>(sym.getRawPtr()));
|
||||
return reinterpret_cast<coff_symbol_generic *>(copy);
|
||||
} else {
|
||||
auto *copy = make<coff_symbol16>(
|
||||
*reinterpret_cast<const coff_symbol16 *>(sym.getRawPtr()));
|
||||
return reinterpret_cast<coff_symbol_generic *>(copy);
|
||||
}
|
||||
}
|
||||
|
||||
ArchiveFile::ArchiveFile(COFFLinkerContext &ctx, MemoryBufferRef m)
|
||||
: InputFile(ctx.symtab, ArchiveKind, m) {}
|
||||
|
||||
@@ -458,9 +470,16 @@ Symbol *ObjFile::createRegular(COFFSymbolRef sym) {
|
||||
return nullptr;
|
||||
return symtab.addUndefined(name, this, false);
|
||||
}
|
||||
if (sc)
|
||||
if (sc) {
|
||||
const coff_symbol_generic *symGen = sym.getGeneric();
|
||||
if (sym.isSection()) {
|
||||
auto *customSymGen = cloneSymbol(sym);
|
||||
customSymGen->Value = 0;
|
||||
symGen = customSymGen;
|
||||
}
|
||||
return make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false,
|
||||
/*IsExternal*/ false, sym.getGeneric(), sc);
|
||||
/*IsExternal*/ false, symGen, sc);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -755,15 +774,23 @@ std::optional<Symbol *> ObjFile::createDefined(
|
||||
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 | IMAGE_SCN_ALIGN_4BYTES;
|
||||
// The Value field in a section symbol may contain the characteristics,
|
||||
// or it may be zero, where we make something up (that matches what is
|
||||
// used in .idata sections in the regular object files in import libraries).
|
||||
if (sym.getValue())
|
||||
hdr->Characteristics = sym.getValue() | IMAGE_SCN_ALIGN_4BYTES;
|
||||
else
|
||||
hdr->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE |
|
||||
IMAGE_SCN_ALIGN_4BYTES;
|
||||
auto *sc = make<SectionChunk>(this, hdr);
|
||||
chunks.push_back(sc);
|
||||
|
||||
auto *symGen = cloneSymbol(sym);
|
||||
// Ignore the Value offset of these symbols, as it may be a bitmask.
|
||||
symGen->Value = 0;
|
||||
return make<DefinedRegular>(this, /*name=*/"", /*isCOMDAT=*/false,
|
||||
/*isExternal=*/false, sym.getGeneric(), sc);
|
||||
/*isExternal=*/false, symGen, sc);
|
||||
}
|
||||
|
||||
if (llvm::COFF::isReservedSectionNumber(sectionNumber))
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# RUN: FileCheck %s --check-prefix=MAP < %t.map
|
||||
|
||||
# CHECK: Contents of section .itest:
|
||||
# CHECK-NEXT: 180001000 0c100080 01000000 00000000 01000000
|
||||
# CHECK-NEXT: 180001000 0c100000 0c100000 00000000 01000000
|
||||
|
||||
# MAP: 00001000 0000000a 4 {{.*}}:(.itest$2)
|
||||
# MAP: 00001000 00000000 0 .itest$2
|
||||
@@ -28,7 +28,10 @@ sections:
|
||||
Relocations:
|
||||
- VirtualAddress: 0
|
||||
SymbolName: '.itest$4'
|
||||
Type: IMAGE_REL_AMD64_ADDR64
|
||||
Type: IMAGE_REL_AMD64_ADDR32NB
|
||||
- VirtualAddress: 4
|
||||
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
|
||||
@@ -42,13 +45,13 @@ symbols:
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_SECTION
|
||||
- Name: '.itest$6'
|
||||
Value: 0
|
||||
Value: 3221225536
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
StorageClass: IMAGE_SYM_CLASS_SECTION
|
||||
- Name: '.itest$4'
|
||||
Value: 0
|
||||
Value: 3221225536
|
||||
SectionNumber: 0
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
|
||||
@@ -383,8 +383,8 @@ public:
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -393,8 +393,7 @@ public:
|
||||
}
|
||||
|
||||
bool isEmptySectionDeclaration() const {
|
||||
return isSection() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
|
||||
getValue() == 0;
|
||||
return isSection() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED;
|
||||
}
|
||||
|
||||
bool isWeakExternal() const {
|
||||
|
||||
@@ -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
|
||||
...
|
||||
Reference in New Issue
Block a user