Skip to content

Commit 3f2921f

Browse files
committedNov 27, 2017
COFF: Do not create SectionChunks for discarded comdat sections.
With this change, instead of creating a SectionChunk for each section in the object file, we only create them when we encounter a prevailing comdat section. Also change how symbol resolution occurs between comdat symbols. Now only the comdat leader participates in comdat resolution, and not any other external associated symbols. This is more in line with how COFF semantics are defined, and should allow for a more straightforward implementation of non-ANY comdat types. On my machine, this change reduces our runtime linking a release build of chrome_child.dll with /nopdb from 5.65s to 4.54s (median of 50 runs). Differential Revision: https://reviews.llvm.org/D40238 llvm-svn: 319090
1 parent 1f34379 commit 3f2921f

File tree

10 files changed

+238
-164
lines changed

10 files changed

+238
-164
lines changed
 

‎lld/COFF/Chunks.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ SectionChunk::SectionChunk(ObjFile *F, const coff_section *H)
3838

3939
Alignment = Header->getAlignment();
4040

41-
// Chunks may be discarded during comdat merging.
42-
Discarded = false;
43-
4441
// If linker GC is disabled, every chunk starts out alive. If linker GC is
4542
// enabled, treat non-comdat sections as roots. Generally optimized object
4643
// files will be built with -ffunction-sections or /Gy, so most things worth
@@ -362,12 +359,8 @@ bool SectionChunk::isCOMDAT() const {
362359
void SectionChunk::printDiscardedMessage() const {
363360
// Removed by dead-stripping. If it's removed by ICF, ICF already
364361
// printed out the name, so don't repeat that here.
365-
if (Sym && this == Repl) {
366-
if (Discarded)
367-
message("Discarded comdat symbol " + Sym->getName());
368-
else if (!Live)
369-
message("Discarded " + Sym->getName());
370-
}
362+
if (Sym && this == Repl)
363+
message("Discarded " + Sym->getName());
371364
}
372365

373366
StringRef SectionChunk::getDebugName() {

‎lld/COFF/Chunks.h

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,9 @@ class SectionChunk final : public Chunk {
159159
void addAssociative(SectionChunk *Child);
160160

161161
StringRef getDebugName() override;
162-
void setSymbol(DefinedRegular *S) { if (!Sym) Sym = S; }
163162

164-
// Returns true if the chunk was not dropped by GC or COMDAT deduplication.
165-
bool isLive() { return Live && !Discarded; }
163+
// Returns true if the chunk was not dropped by GC.
164+
bool isLive() { return Live; }
166165

167166
// Used by the garbage collector.
168167
void markLive() {
@@ -171,13 +170,6 @@ class SectionChunk final : public Chunk {
171170
Live = true;
172171
}
173172

174-
// Returns true if this chunk was dropped by COMDAT deduplication.
175-
bool isDiscarded() const { return Discarded; }
176-
177-
// Used by the SymbolTable when discarding unused comdat sections. This is
178-
// redundant when GC is enabled, as all comdat sections will start out dead.
179-
void markDiscarded() { Discarded = true; }
180-
181173
// True if this is a codeview debug info chunk. These will not be laid out in
182174
// the image. Instead they will end up in the PDB, if one is requested.
183175
bool isCodeView() const {
@@ -213,24 +205,21 @@ class SectionChunk final : public Chunk {
213205
// The file that this chunk was created from.
214206
ObjFile *File;
215207

208+
// The COMDAT leader symbol if this is a COMDAT chunk.
209+
DefinedRegular *Sym = nullptr;
210+
216211
private:
217212
StringRef SectionName;
218213
std::vector<SectionChunk *> AssocChildren;
219214
llvm::iterator_range<const coff_relocation *> Relocs;
220215
size_t NumRelocs;
221216

222-
// True if this chunk was discarded because it was a duplicate comdat section.
223-
bool Discarded;
224-
225217
// Used by the garbage collector.
226218
bool Live;
227219

228220
// Used for ICF (Identical COMDAT Folding)
229221
void replace(SectionChunk *Other);
230222
uint32_t Class[2] = {0, 0};
231-
232-
// Sym points to a section symbol if this is a COMDAT chunk.
233-
DefinedRegular *Sym = nullptr;
234223
};
235224

236225
// A chunk for common symbols. Common chunks don't have actual data.

‎lld/COFF/InputFiles.cpp

Lines changed: 177 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -119,86 +119,158 @@ void ObjFile::parse() {
119119
initializeSEH();
120120
}
121121

122+
// We set SectionChunk pointers in the SparseChunks vector to this value
123+
// temporarily to mark comdat sections as having an unknown resolution. As we
124+
// walk the object file's symbol table, once we visit either a leader symbol or
125+
// an associative section definition together with the parent comdat's leader,
126+
// we set the pointer to either nullptr (to mark the section as discarded) or a
127+
// valid SectionChunk for that section.
128+
static SectionChunk *const PendingComdat = reinterpret_cast<SectionChunk *>(1);
129+
122130
void ObjFile::initializeChunks() {
123131
uint32_t NumSections = COFFObj->getNumberOfSections();
124132
Chunks.reserve(NumSections);
125133
SparseChunks.resize(NumSections + 1);
126134
for (uint32_t I = 1; I < NumSections + 1; ++I) {
127135
const coff_section *Sec;
128-
StringRef Name;
129136
if (auto EC = COFFObj->getSection(I, Sec))
130137
fatal("getSection failed: #" + Twine(I) + ": " + EC.message());
131-
if (auto EC = COFFObj->getSectionName(Sec, Name))
132-
fatal("getSectionName failed: #" + Twine(I) + ": " + EC.message());
133-
if (Name == ".sxdata") {
134-
SXData = Sec;
135-
continue;
136-
}
137-
if (Name == ".drectve") {
138-
ArrayRef<uint8_t> Data;
139-
COFFObj->getSectionContents(Sec, Data);
140-
Directives = std::string((const char *)Data.data(), Data.size());
141-
continue;
142-
}
143138

144-
// Object files may have DWARF debug info or MS CodeView debug info
145-
// (or both).
146-
//
147-
// DWARF sections don't need any special handling from the perspective
148-
// of the linker; they are just a data section containing relocations.
149-
// We can just link them to complete debug info.
150-
//
151-
// CodeView needs a linker support. We need to interpret and debug
152-
// info, and then write it to a separate .pdb file.
153-
154-
// Ignore debug info unless /debug is given.
155-
if (!Config->Debug && Name.startswith(".debug"))
156-
continue;
157-
158-
if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE)
159-
continue;
160-
auto *C = make<SectionChunk>(this, Sec);
161-
162-
// CodeView sections are stored to a different vector because they are not
163-
// linked in the regular manner.
164-
if (C->isCodeView())
165-
DebugChunks.push_back(C);
139+
if (Sec->Characteristics & IMAGE_SCN_LNK_COMDAT)
140+
SparseChunks[I] = PendingComdat;
166141
else
167-
Chunks.push_back(C);
142+
SparseChunks[I] = readSection(I, nullptr);
143+
}
144+
}
168145

169-
SparseChunks[I] = C;
146+
SectionChunk *ObjFile::readSection(uint32_t SectionNumber,
147+
const coff_aux_section_definition *Def) {
148+
const coff_section *Sec;
149+
StringRef Name;
150+
if (auto EC = COFFObj->getSection(SectionNumber, Sec))
151+
fatal("getSection failed: #" + Twine(SectionNumber) + ": " + EC.message());
152+
if (auto EC = COFFObj->getSectionName(Sec, Name))
153+
fatal("getSectionName failed: #" + Twine(SectionNumber) + ": " +
154+
EC.message());
155+
if (Name == ".sxdata") {
156+
SXData = Sec;
157+
return nullptr;
158+
}
159+
if (Name == ".drectve") {
160+
ArrayRef<uint8_t> Data;
161+
COFFObj->getSectionContents(Sec, Data);
162+
Directives = std::string((const char *)Data.data(), Data.size());
163+
return nullptr;
170164
}
165+
166+
// Object files may have DWARF debug info or MS CodeView debug info
167+
// (or both).
168+
//
169+
// DWARF sections don't need any special handling from the perspective
170+
// of the linker; they are just a data section containing relocations.
171+
// We can just link them to complete debug info.
172+
//
173+
// CodeView needs a linker support. We need to interpret and debug
174+
// info, and then write it to a separate .pdb file.
175+
176+
// Ignore debug info unless /debug is given.
177+
if (!Config->Debug && Name.startswith(".debug"))
178+
return nullptr;
179+
180+
if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE)
181+
return nullptr;
182+
auto *C = make<SectionChunk>(this, Sec);
183+
if (Def)
184+
C->Checksum = Def->CheckSum;
185+
186+
// CodeView sections are stored to a different vector because they are not
187+
// linked in the regular manner.
188+
if (C->isCodeView())
189+
DebugChunks.push_back(C);
190+
else
191+
Chunks.push_back(C);
192+
193+
return C;
194+
}
195+
196+
void ObjFile::readAssociativeDefinition(
197+
COFFSymbolRef Sym, const coff_aux_section_definition *Def) {
198+
SectionChunk *Parent = SparseChunks[Def->getNumber(Sym.isBigObj())];
199+
200+
// If the parent is pending, it probably means that its section definition
201+
// appears after us in the symbol table. Leave the associated section as
202+
// pending; we will handle it during the second pass in initializeSymbols().
203+
if (Parent == PendingComdat)
204+
return;
205+
206+
// Check whether the parent is prevailing. If it is, so are we, and we read
207+
// the section; otherwise mark it as discarded.
208+
int32_t SectionNumber = Sym.getSectionNumber();
209+
if (Parent) {
210+
SparseChunks[SectionNumber] = readSection(SectionNumber, Def);
211+
Parent->addAssociative(SparseChunks[SectionNumber]);
212+
} else {
213+
SparseChunks[SectionNumber] = nullptr;
214+
}
215+
}
216+
217+
Symbol *ObjFile::createRegular(COFFSymbolRef Sym) {
218+
SectionChunk *SC = SparseChunks[Sym.getSectionNumber()];
219+
if (Sym.isExternal()) {
220+
StringRef Name;
221+
COFFObj->getSymbolName(Sym, Name);
222+
if (SC)
223+
return Symtab->addRegular(this, Name, Sym.getGeneric(), SC);
224+
return Symtab->addUndefined(Name, this, false);
225+
}
226+
if (SC)
227+
return make<DefinedRegular>(this, /*Name*/ "", false,
228+
/*IsExternal*/ false, Sym.getGeneric(), SC);
229+
return nullptr;
171230
}
172231

173232
void ObjFile::initializeSymbols() {
174233
uint32_t NumSymbols = COFFObj->getNumberOfSymbols();
175234
Symbols.resize(NumSymbols);
176235

177236
SmallVector<std::pair<Symbol *, uint32_t>, 8> WeakAliases;
178-
int32_t LastSectionNumber = 0;
237+
std::vector<uint32_t> PendingIndexes;
238+
PendingIndexes.reserve(NumSymbols);
239+
240+
std::vector<const coff_aux_section_definition *> ComdatDefs(
241+
COFFObj->getNumberOfSections() + 1);
179242

180243
for (uint32_t I = 0; I < NumSymbols; ++I) {
181244
COFFSymbolRef COFFSym = check(COFFObj->getSymbol(I));
182-
183-
const void *AuxP = nullptr;
184-
if (COFFSym.getNumberOfAuxSymbols())
185-
AuxP = check(COFFObj->getSymbol(I + 1)).getRawPtr();
186-
bool IsFirst = (LastSectionNumber != COFFSym.getSectionNumber());
187-
188-
Symbol *Sym = nullptr;
189245
if (COFFSym.isUndefined()) {
190-
Sym = createUndefined(COFFSym);
246+
Symbols[I] = createUndefined(COFFSym);
191247
} else if (COFFSym.isWeakExternal()) {
192-
Sym = createUndefined(COFFSym);
193-
uint32_t TagIndex =
194-
static_cast<const coff_aux_weak_external *>(AuxP)->TagIndex;
195-
WeakAliases.emplace_back(Sym, TagIndex);
248+
Symbols[I] = createUndefined(COFFSym);
249+
uint32_t TagIndex = COFFSym.getAux<coff_aux_weak_external>()->TagIndex;
250+
WeakAliases.emplace_back(Symbols[I], TagIndex);
251+
} else if (Optional<Symbol *> OptSym = createDefined(COFFSym, ComdatDefs)) {
252+
Symbols[I] = *OptSym;
196253
} else {
197-
Sym = createDefined(COFFSym, AuxP, IsFirst);
254+
// createDefined() returns None if a symbol belongs to a section that
255+
// was pending at the point when the symbol was read. This can happen in
256+
// two cases:
257+
// 1) section definition symbol for a comdat leader;
258+
// 2) symbol belongs to a comdat section associated with a section whose
259+
// section definition symbol appears later in the symbol table.
260+
// In both of these cases, we can expect the section to be resolved by
261+
// the time we finish visiting the remaining symbols in the symbol
262+
// table. So we postpone the handling of this symbol until that time.
263+
PendingIndexes.push_back(I);
198264
}
199-
Symbols[I] = Sym;
200265
I += COFFSym.getNumberOfAuxSymbols();
201-
LastSectionNumber = COFFSym.getSectionNumber();
266+
}
267+
268+
for (uint32_t I : PendingIndexes) {
269+
COFFSymbolRef Sym = check(COFFObj->getSymbol(I));
270+
if (auto *Def = Sym.getSectionDefinition())
271+
if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE)
272+
readAssociativeDefinition(Sym, Def);
273+
Symbols[I] = createRegular(Sym);
202274
}
203275

204276
for (auto &KV : WeakAliases) {
@@ -214,8 +286,9 @@ Symbol *ObjFile::createUndefined(COFFSymbolRef Sym) {
214286
return Symtab->addUndefined(Name, this, Sym.isWeakExternal());
215287
}
216288

217-
Symbol *ObjFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
218-
bool IsFirst) {
289+
Optional<Symbol *> ObjFile::createDefined(
290+
COFFSymbolRef Sym,
291+
std::vector<const coff_aux_section_definition *> &ComdatDefs) {
219292
StringRef Name;
220293
if (Sym.isCommon()) {
221294
auto *C = make<CommonChunk>(Sym);
@@ -254,37 +327,46 @@ Symbol *ObjFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
254327
if ((uint32_t)SectionNumber >= SparseChunks.size())
255328
fatal("broken object file: " + toString(this));
256329

257-
// Nothing else to do without a section chunk.
258-
auto *SC = SparseChunks[SectionNumber];
259-
if (!SC)
260-
return nullptr;
330+
// Handle comdat leader symbols.
331+
if (const coff_aux_section_definition *Def = ComdatDefs[SectionNumber]) {
332+
ComdatDefs[SectionNumber] = nullptr;
333+
Symbol *Leader;
334+
bool Prevailing;
335+
if (Sym.isExternal()) {
336+
COFFObj->getSymbolName(Sym, Name);
337+
std::tie(Leader, Prevailing) =
338+
Symtab->addComdat(this, Name, Sym.getGeneric());
339+
} else {
340+
Leader = make<DefinedRegular>(this, /*Name*/ "", false,
341+
/*IsExternal*/ false, Sym.getGeneric());
342+
Prevailing = true;
343+
}
344+
if (Prevailing) {
345+
SectionChunk *C = readSection(SectionNumber, Def);
346+
SparseChunks[SectionNumber] = C;
347+
C->Sym = cast<DefinedRegular>(Leader);
348+
cast<DefinedRegular>(Leader)->Data = &C->Repl;
349+
} else {
350+
SparseChunks[SectionNumber] = nullptr;
351+
}
352+
return Leader;
353+
}
261354

262-
// Handle section definitions
263-
if (IsFirst && AuxP) {
264-
auto *Aux = reinterpret_cast<const coff_aux_section_definition *>(AuxP);
265-
if (Aux->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE)
266-
if (auto *ParentSC = SparseChunks[Aux->getNumber(Sym.isBigObj())]) {
267-
ParentSC->addAssociative(SC);
268-
// If we already discarded the parent, discard the child.
269-
if (ParentSC->isDiscarded())
270-
SC->markDiscarded();
271-
}
272-
SC->Checksum = Aux->CheckSum;
355+
// Read associative section definitions and prepare to handle the comdat
356+
// leader symbol by setting the section's ComdatDefs pointer if we encounter a
357+
// non-associative comdat.
358+
if (SparseChunks[SectionNumber] == PendingComdat) {
359+
if (auto *Def = Sym.getSectionDefinition()) {
360+
if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE)
361+
readAssociativeDefinition(Sym, Def);
362+
else
363+
ComdatDefs[SectionNumber] = Def;
364+
}
273365
}
274366

275-
DefinedRegular *B;
276-
if (Sym.isExternal()) {
277-
COFFObj->getSymbolName(Sym, Name);
278-
Symbol *S =
279-
Symtab->addRegular(this, Name, SC->isCOMDAT(), Sym.getGeneric(), SC);
280-
B = cast<DefinedRegular>(S);
281-
} else
282-
B = make<DefinedRegular>(this, /*Name*/ "", SC->isCOMDAT(),
283-
/*IsExternal*/ false, Sym.getGeneric(), SC);
284-
if (SC->isCOMDAT() && Sym.getValue() == 0 && !AuxP)
285-
SC->setSymbol(B);
286-
287-
return B;
367+
if (SparseChunks[SectionNumber] == PendingComdat)
368+
return None;
369+
return createRegular(Sym);
288370
}
289371

290372
void ObjFile::initializeSEH() {
@@ -361,8 +443,12 @@ void ImportFile::parse() {
361443
void BitcodeFile::parse() {
362444
Obj = check(lto::InputFile::create(MemoryBufferRef(
363445
MB.getBuffer(), Saver.save(ParentName + MB.getBufferIdentifier()))));
446+
std::vector<std::pair<Symbol *, bool>> Comdat(Obj->getComdatTable().size());
447+
for (size_t I = 0; I != Obj->getComdatTable().size(); ++I)
448+
Comdat[I] = Symtab->addComdat(this, Saver.save(Obj->getComdatTable()[I]));
364449
for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) {
365450
StringRef SymName = Saver.save(ObjSym.getName());
451+
int ComdatIndex = ObjSym.getComdatIndex();
366452
Symbol *Sym;
367453
if (ObjSym.isUndefined()) {
368454
Sym = Symtab->addUndefined(SymName, this, false);
@@ -374,9 +460,15 @@ void BitcodeFile::parse() {
374460
std::string Fallback = ObjSym.getCOFFWeakExternalFallback();
375461
Symbol *Alias = Symtab->addUndefined(Saver.save(Fallback));
376462
checkAndSetWeakAlias(Symtab, this, Sym, Alias);
463+
} else if (ComdatIndex != -1) {
464+
if (SymName == Obj->getComdatTable()[ComdatIndex])
465+
Sym = Comdat[ComdatIndex].first;
466+
else if (Comdat[ComdatIndex].second)
467+
Sym = Symtab->addRegular(this, SymName);
468+
else
469+
Sym = Symtab->addUndefined(SymName, this, false);
377470
} else {
378-
bool IsCOMDAT = ObjSym.getComdatIndex() != -1;
379-
Sym = Symtab->addRegular(this, SymName, IsCOMDAT);
471+
Sym = Symtab->addRegular(this, SymName);
380472
}
381473
SymbolBodies.push_back(Sym);
382474
}

‎lld/COFF/InputFiles.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,19 @@ class ObjFile : public InputFile {
142142
void initializeSymbols();
143143
void initializeSEH();
144144

145-
Symbol *createDefined(COFFSymbolRef Sym, const void *Aux, bool IsFirst);
145+
SectionChunk *
146+
readSection(uint32_t SectionNumber,
147+
const llvm::object::coff_aux_section_definition *Def);
148+
149+
void readAssociativeDefinition(
150+
COFFSymbolRef COFFSym,
151+
const llvm::object::coff_aux_section_definition *Def);
152+
153+
llvm::Optional<Symbol *>
154+
createDefined(COFFSymbolRef Sym,
155+
std::vector<const llvm::object::coff_aux_section_definition *>
156+
&ComdatDefs);
157+
Symbol *createRegular(COFFSymbolRef Sym);
146158
Symbol *createUndefined(COFFSymbolRef Sym);
147159

148160
std::unique_ptr<COFFObjectFile> COFFObj;

‎lld/COFF/MarkLive.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,6 @@ void markLive(const std::vector<Chunk *> &Chunks) {
5252

5353
while (!Worklist.empty()) {
5454
SectionChunk *SC = Worklist.pop_back_val();
55-
56-
// If this section was discarded, there are relocations referring to
57-
// discarded sections. Ignore these sections to avoid crashing. They will be
58-
// diagnosed during relocation processing.
59-
if (SC->isDiscarded())
60-
continue;
61-
6255
assert(SC->isLive() && "We mark as live when pushing onto the worklist!");
6356

6457
// Mark all symbols listed in the relocation table for this section.

‎lld/COFF/SymbolTable.cpp

Lines changed: 23 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,36 +24,6 @@ using namespace llvm;
2424
namespace lld {
2525
namespace coff {
2626

27-
enum SymbolPreference {
28-
SP_EXISTING = -1,
29-
SP_CONFLICT = 0,
30-
SP_NEW = 1,
31-
};
32-
33-
/// Checks if an existing symbol S should be kept or replaced by a new symbol.
34-
/// Returns SP_EXISTING when S should be kept, SP_NEW when the new symbol
35-
/// should be kept, and SP_CONFLICT if no valid resolution exists.
36-
static SymbolPreference compareDefined(Symbol *S, bool WasInserted,
37-
bool NewIsCOMDAT) {
38-
// If the symbol wasn't previously known, the new symbol wins by default.
39-
if (WasInserted || !isa<Defined>(S))
40-
return SP_NEW;
41-
42-
// If the existing symbol is a DefinedRegular, both it and the new symbol
43-
// must be comdats. In that case, we have no reason to prefer one symbol
44-
// over the other, and we keep the existing one. If one of the symbols
45-
// is not a comdat, we report a conflict.
46-
if (auto *R = dyn_cast<DefinedRegular>(S)) {
47-
if (NewIsCOMDAT && R->isCOMDAT())
48-
return SP_EXISTING;
49-
else
50-
return SP_CONFLICT;
51-
}
52-
53-
// Existing symbol is not a DefinedRegular; new symbol wins.
54-
return SP_NEW;
55-
}
56-
5727
SymbolTable *Symtab;
5828

5929
void SymbolTable::addFile(InputFile *File) {
@@ -240,30 +210,40 @@ Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) {
240210
return S;
241211
}
242212

243-
Symbol *SymbolTable::addRegular(InputFile *F, StringRef N, bool IsCOMDAT,
213+
Symbol *SymbolTable::addRegular(InputFile *F, StringRef N,
244214
const coff_symbol_generic *Sym,
245215
SectionChunk *C) {
246216
Symbol *S;
247217
bool WasInserted;
248218
std::tie(S, WasInserted) = insert(N);
249219
if (!isa<BitcodeFile>(F))
250220
S->IsUsedInRegularObj = true;
251-
SymbolPreference SP = compareDefined(S, WasInserted, IsCOMDAT);
252-
if (SP == SP_CONFLICT) {
221+
if (WasInserted || !isa<DefinedRegular>(S))
222+
replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ false,
223+
/*IsExternal*/ true, Sym, C);
224+
else
253225
reportDuplicate(S, F);
254-
} else if (SP == SP_NEW) {
255-
replaceSymbol<DefinedRegular>(S, F, N, IsCOMDAT, /*IsExternal*/ true, Sym,
256-
C);
257-
} else if (SP == SP_EXISTING && IsCOMDAT && C) {
258-
C->markDiscarded();
259-
// Discard associative chunks that we've parsed so far. No need to recurse
260-
// because an associative section cannot have children.
261-
for (SectionChunk *Child : C->children())
262-
Child->markDiscarded();
263-
}
264226
return S;
265227
}
266228

229+
std::pair<Symbol *, bool>
230+
SymbolTable::addComdat(InputFile *F, StringRef N,
231+
const coff_symbol_generic *Sym) {
232+
Symbol *S;
233+
bool WasInserted;
234+
std::tie(S, WasInserted) = insert(N);
235+
if (!isa<BitcodeFile>(F))
236+
S->IsUsedInRegularObj = true;
237+
if (WasInserted || !isa<DefinedRegular>(S)) {
238+
replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ true,
239+
/*IsExternal*/ true, Sym, nullptr);
240+
return {S, true};
241+
}
242+
if (!cast<DefinedRegular>(S)->isCOMDAT())
243+
reportDuplicate(S, F);
244+
return {S, false};
245+
}
246+
267247
Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size,
268248
const coff_symbol_generic *Sym, CommonChunk *C) {
269249
Symbol *S;

‎lld/COFF/SymbolTable.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,12 @@ class SymbolTable {
8383
Symbol *addUndefined(StringRef Name, InputFile *F, bool IsWeakAlias);
8484
void addLazy(ArchiveFile *F, const Archive::Symbol Sym);
8585
Symbol *addAbsolute(StringRef N, COFFSymbolRef S);
86-
Symbol *addRegular(InputFile *F, StringRef N, bool IsCOMDAT,
86+
Symbol *addRegular(InputFile *F, StringRef N,
8787
const llvm::object::coff_symbol_generic *S = nullptr,
8888
SectionChunk *C = nullptr);
89+
std::pair<Symbol *, bool>
90+
addComdat(InputFile *F, StringRef N,
91+
const llvm::object::coff_symbol_generic *S = nullptr);
8992
Symbol *addCommon(InputFile *F, StringRef N, uint64_t Size,
9093
const llvm::object::coff_symbol_generic *S = nullptr,
9194
CommonChunk *C = nullptr);

‎lld/COFF/Symbols.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ class DefinedRegular : public DefinedCOFF {
169169
SectionChunk *getChunk() const { return *Data; }
170170
uint32_t getValue() const { return Sym->Value; }
171171

172-
private:
173172
SectionChunk **Data;
174173
};
175174

‎lld/test/COFF/reloc-discarded.s

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ main_global:
1818

1919
.section .CRT$XCU,"dr",associative,main_global
2020
.p2align 3
21-
.globl assoc_global
2221
assoc_global:
2322
.quad main_global
2423

‎llvm/include/llvm/Object/COFF.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,8 @@ struct coff_symbol_generic {
275275
support::ulittle32_t Value;
276276
};
277277

278+
struct coff_aux_section_definition;
279+
278280
class COFFSymbolRef {
279281
public:
280282
COFFSymbolRef() = default;
@@ -346,6 +348,18 @@ class COFFSymbolRef {
346348
return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT;
347349
}
348350

351+
template <typename T> const T *getAux() const {
352+
return CS16 ? reinterpret_cast<const T *>(CS16 + 1)
353+
: reinterpret_cast<const T *>(CS32 + 1);
354+
}
355+
356+
const coff_aux_section_definition *getSectionDefinition() const {
357+
if (!getNumberOfAuxSymbols() ||
358+
getStorageClass() != COFF::IMAGE_SYM_CLASS_STATIC)
359+
return nullptr;
360+
return getAux<coff_aux_section_definition>();
361+
}
362+
349363
bool isAbsolute() const {
350364
return getSectionNumber() == -1;
351365
}

0 commit comments

Comments
 (0)
Please sign in to comment.