@@ -119,86 +119,158 @@ void ObjFile::parse() {
119
119
initializeSEH ();
120
120
}
121
121
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
+
122
130
void ObjFile::initializeChunks () {
123
131
uint32_t NumSections = COFFObj->getNumberOfSections ();
124
132
Chunks.reserve (NumSections);
125
133
SparseChunks.resize (NumSections + 1 );
126
134
for (uint32_t I = 1 ; I < NumSections + 1 ; ++I) {
127
135
const coff_section *Sec;
128
- StringRef Name;
129
136
if (auto EC = COFFObj->getSection (I, Sec))
130
137
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
- }
143
138
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;
166
141
else
167
- Chunks.push_back (C);
142
+ SparseChunks[I] = readSection (I, nullptr );
143
+ }
144
+ }
168
145
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 ;
170
164
}
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 ;
171
230
}
172
231
173
232
void ObjFile::initializeSymbols () {
174
233
uint32_t NumSymbols = COFFObj->getNumberOfSymbols ();
175
234
Symbols.resize (NumSymbols);
176
235
177
236
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 );
179
242
180
243
for (uint32_t I = 0 ; I < NumSymbols; ++I) {
181
244
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 ;
189
245
if (COFFSym.isUndefined ()) {
190
- Sym = createUndefined (COFFSym);
246
+ Symbols[I] = createUndefined (COFFSym);
191
247
} 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;
196
253
} 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);
198
264
}
199
- Symbols[I] = Sym;
200
265
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);
202
274
}
203
275
204
276
for (auto &KV : WeakAliases) {
@@ -214,8 +286,9 @@ Symbol *ObjFile::createUndefined(COFFSymbolRef Sym) {
214
286
return Symtab->addUndefined (Name, this , Sym.isWeakExternal ());
215
287
}
216
288
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) {
219
292
StringRef Name;
220
293
if (Sym.isCommon ()) {
221
294
auto *C = make<CommonChunk>(Sym);
@@ -254,37 +327,46 @@ Symbol *ObjFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
254
327
if ((uint32_t )SectionNumber >= SparseChunks.size ())
255
328
fatal (" broken object file: " + toString (this ));
256
329
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
+ }
261
354
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
+ }
273
365
}
274
366
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);
288
370
}
289
371
290
372
void ObjFile::initializeSEH () {
@@ -361,8 +443,12 @@ void ImportFile::parse() {
361
443
void BitcodeFile::parse () {
362
444
Obj = check (lto::InputFile::create (MemoryBufferRef (
363
445
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]));
364
449
for (const lto::InputFile::Symbol &ObjSym : Obj->symbols ()) {
365
450
StringRef SymName = Saver.save (ObjSym.getName ());
451
+ int ComdatIndex = ObjSym.getComdatIndex ();
366
452
Symbol *Sym;
367
453
if (ObjSym.isUndefined ()) {
368
454
Sym = Symtab->addUndefined (SymName, this , false );
@@ -374,9 +460,15 @@ void BitcodeFile::parse() {
374
460
std::string Fallback = ObjSym.getCOFFWeakExternalFallback ();
375
461
Symbol *Alias = Symtab->addUndefined (Saver.save (Fallback));
376
462
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 );
377
470
} else {
378
- bool IsCOMDAT = ObjSym.getComdatIndex () != -1 ;
379
- Sym = Symtab->addRegular (this , SymName, IsCOMDAT);
471
+ Sym = Symtab->addRegular (this , SymName);
380
472
}
381
473
SymbolBodies.push_back (Sym);
382
474
}
0 commit comments