forked from OSchip/llvm-project
[LLD] [COFF] Check the aux section definition size for IMAGE_COMDAT_SELECT_SAME_SIZE
Binutils generated sections seem to be padded to a multiple of 16 bytes, but the aux section definition contains the original, unpadded section length. The size check used for IMAGE_COMDAT_SELECT_SAME_SIZE previously only checked the size of the section itself. When checking the currently processed object file against the previously chosen comdat section, we easily have access to the aux section definition of the currently processed section, but we have to iterate over the symbols of the previously selected object file to find the section definition of the previously picked section. (We don't want to inflate SectionChunk to carry more data, for something that is only needed in corner cases.) Only do this when the mingw flag is set. This fixes statically linking clang-built C++ object files against libstdc++ built with GCC, if the object files contain e.g. typeinfo. Differential Revision: https://reviews.llvm.org/D86659
This commit is contained in:
parent
e72403f96d
commit
df8f3bf626
|
@ -472,8 +472,23 @@ Symbol *ObjFile::createUndefined(COFFSymbolRef sym) {
|
|||
return symtab->addUndefined(name, this, sym.isWeakExternal());
|
||||
}
|
||||
|
||||
void ObjFile::handleComdatSelection(COFFSymbolRef sym, COMDATType &selection,
|
||||
bool &prevailing, DefinedRegular *leader) {
|
||||
static const coff_aux_section_definition *findSectionDef(COFFObjectFile *obj,
|
||||
int32_t section) {
|
||||
uint32_t numSymbols = obj->getNumberOfSymbols();
|
||||
for (uint32_t i = 0; i < numSymbols; ++i) {
|
||||
COFFSymbolRef sym = check(obj->getSymbol(i));
|
||||
if (sym.getSectionNumber() != section)
|
||||
continue;
|
||||
if (const coff_aux_section_definition *def = sym.getSectionDefinition())
|
||||
return def;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ObjFile::handleComdatSelection(
|
||||
COFFSymbolRef sym, COMDATType &selection, bool &prevailing,
|
||||
DefinedRegular *leader,
|
||||
const llvm::object::coff_aux_section_definition *def) {
|
||||
if (prevailing)
|
||||
return;
|
||||
// There's already an existing comdat for this symbol: `Leader`.
|
||||
|
@ -540,8 +555,16 @@ void ObjFile::handleComdatSelection(COFFSymbolRef sym, COMDATType &selection,
|
|||
break;
|
||||
|
||||
case IMAGE_COMDAT_SELECT_SAME_SIZE:
|
||||
if (leaderChunk->getSize() != getSection(sym)->SizeOfRawData)
|
||||
symtab->reportDuplicate(leader, this);
|
||||
if (leaderChunk->getSize() != getSection(sym)->SizeOfRawData) {
|
||||
if (!config->mingw) {
|
||||
symtab->reportDuplicate(leader, this);
|
||||
} else {
|
||||
const coff_aux_section_definition *leaderDef = findSectionDef(
|
||||
leaderChunk->file->getCOFFObj(), leaderChunk->getSectionNumber());
|
||||
if (!leaderDef || leaderDef->Length != def->Length)
|
||||
symtab->reportDuplicate(leader, this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGE_COMDAT_SELECT_EXACT_MATCH: {
|
||||
|
@ -657,7 +680,7 @@ Optional<Symbol *> ObjFile::createDefined(
|
|||
COMDATType selection = (COMDATType)def->Selection;
|
||||
|
||||
if (leader->isCOMDAT)
|
||||
handleComdatSelection(sym, selection, prevailing, leader);
|
||||
handleComdatSelection(sym, selection, prevailing, leader, def);
|
||||
|
||||
if (prevailing) {
|
||||
SectionChunk *c = readSection(sectionNumber, def, getName());
|
||||
|
|
|
@ -255,9 +255,10 @@ private:
|
|||
// match the existing symbol and its selection. If either old or new
|
||||
// symbol have selection IMAGE_COMDAT_SELECT_LARGEST, Sym might replace
|
||||
// the existing leader. In that case, Prevailing is set to true.
|
||||
void handleComdatSelection(COFFSymbolRef sym,
|
||||
llvm::COFF::COMDATType &selection,
|
||||
bool &prevailing, DefinedRegular *leader);
|
||||
void
|
||||
handleComdatSelection(COFFSymbolRef sym, llvm::COFF::COMDATType &selection,
|
||||
bool &prevailing, DefinedRegular *leader,
|
||||
const llvm::object::coff_aux_section_definition *def);
|
||||
|
||||
llvm::Optional<Symbol *>
|
||||
createDefined(COFFSymbolRef sym,
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ IMAGE_FILE_RELOCS_STRIPPED, IMAGE_FILE_LINE_NUMS_STRIPPED ]
|
||||
sections:
|
||||
- Name: '.rdata$mysymbol'
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: 2A000000000000000000000000000000
|
||||
symbols:
|
||||
- Name: '.rdata$mysymbol'
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
Selection: IMAGE_COMDAT_SELECT_SAME_SIZE
|
||||
- Name: mysymbol
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
|
@ -0,0 +1,30 @@
|
|||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: '.rdata$mysymbol'
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 1
|
||||
SectionData: 2A
|
||||
symbols:
|
||||
- Name: '.rdata$mysymbol'
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 3686517206
|
||||
Number: 1
|
||||
Selection: IMAGE_COMDAT_SELECT_SAME_SIZE
|
||||
- Name: mysymbol
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
|
@ -0,0 +1,15 @@
|
|||
# RUN: yaml2obj %p/Inputs/comdat-llvm.yaml > %t.llvm.o
|
||||
# RUN: yaml2obj %p/Inputs/comdat-binutils.yaml > %t.binutils.o
|
||||
# RUN: lld-link -lldmingw -noentry -dll %t.llvm.o %t.binutils.o -out:%t.dll
|
||||
# RUN: lld-link -lldmingw -noentry -dll %t.binutils.o %t.llvm.o -out:%t.dll
|
||||
# RUN: not lld-link -noentry -dll %t.llvm.o %t.binutils.o -out:%t.dll
|
||||
# RUN: not lld-link -noentry -dll %t.binutils.o %t.llvm.o -out:%t.dll
|
||||
|
||||
# The test object files have been generated by assembling the following
|
||||
# snippet using binutils and llvm.
|
||||
|
||||
# .section .rdata$mysymbol, "dr"
|
||||
# .linkonce same_size
|
||||
# .globl mysymbol
|
||||
#mysymbol:
|
||||
# .byte 42
|
Loading…
Reference in New Issue