@@ -209,12 +209,23 @@ class Writer {
209
209
OutputSection *TextSec;
210
210
OutputSection *RdataSec;
211
211
OutputSection *DataSec;
212
- OutputSection *PdataSec;
213
212
OutputSection *IdataSec;
214
213
OutputSection *EdataSec;
215
214
OutputSection *DidatSec;
216
215
OutputSection *RsrcSec;
217
216
OutputSection *RelocSec;
217
+
218
+ // The first and last .pdata sections in the output file.
219
+ //
220
+ // We need to keep track of the location of .pdata in whichever section it
221
+ // gets merged into so that we can sort its contents and emit a correct data
222
+ // directory entry for the exception table. This is also the case for some
223
+ // other sections (such as .edata) but because the contents of those sections
224
+ // are entirely linker-generated we can keep track of their locations using
225
+ // the chunks that the linker creates. All .pdata chunks come from input
226
+ // files, so we need to keep track of them separately.
227
+ Chunk *FirstPdata = nullptr ;
228
+ Chunk *LastPdata;
218
229
};
219
230
} // anonymous namespace
220
231
@@ -362,17 +373,12 @@ void Writer::run() {
362
373
fatal (" failed to write the output file: " + toString (std::move (E)));
363
374
}
364
375
365
- static StringRef getOutputSection (StringRef Name) {
376
+ static StringRef getOutputSectionName (StringRef Name) {
366
377
StringRef S = Name.split (' $' ).first ;
367
378
368
379
// Treat a later period as a separator for MinGW, for sections like
369
380
// ".ctors.01234".
370
- S = S.substr (0 , S.find (' .' , 1 ));
371
-
372
- auto It = Config->Merge .find (S);
373
- if (It == Config->Merge .end ())
374
- return S;
375
- return It->second ;
381
+ return S.substr (0 , S.find (' .' , 1 ));
376
382
}
377
383
378
384
// For /order.
@@ -403,10 +409,15 @@ void Writer::createSections() {
403
409
404
410
SmallDenseMap<StringRef, OutputSection *> Sections;
405
411
auto CreateSection = [&](StringRef Name, uint32_t Perms) {
406
- auto Sec = make<OutputSection>(Name);
412
+ auto I = Config->Merge .find (Name);
413
+ if (I != Config->Merge .end ())
414
+ Name = I->second ;
415
+ OutputSection *&Sec = Sections[Name];
416
+ if (!Sec) {
417
+ Sec = make<OutputSection>(Name);
418
+ OutputSections.push_back (Sec);
419
+ }
407
420
Sec->addPermissions (Perms);
408
- OutputSections.push_back (Sec);
409
- Sections[Name] = Sec;
410
421
return Sec;
411
422
};
412
423
@@ -415,7 +426,7 @@ void Writer::createSections() {
415
426
CreateSection (" .bss" , BSS | R | W);
416
427
RdataSec = CreateSection (" .rdata" , DATA | R);
417
428
DataSec = CreateSection (" .data" , DATA | R | W);
418
- PdataSec = CreateSection (" .pdata" , DATA | R);
429
+ CreateSection (" .pdata" , DATA | R);
419
430
IdataSec = CreateSection (" .idata" , DATA | R);
420
431
EdataSec = CreateSection (" .edata" , DATA | R);
421
432
DidatSec = CreateSection (" .didat" , DATA | R);
@@ -444,12 +455,13 @@ void Writer::createSections() {
444
455
// discarded when determining output section. So, .text$foo
445
456
// contributes to .text, for example. See PE/COFF spec 3.2.
446
457
for (auto Pair : Map) {
447
- StringRef Name = getOutputSection (Pair.first );
448
- OutputSection *&Sec = Sections[Name];
449
- if (!Sec) {
450
- Sec = make<OutputSection>(Name );
451
- OutputSections. push_back (Sec );
458
+ StringRef Name = getOutputSectionName (Pair.first );
459
+ if (Name == " .pdata " ) {
460
+ if (!FirstPdata)
461
+ FirstPdata = Pair. second . front ( );
462
+ LastPdata = Pair. second . back ( );
452
463
}
464
+ OutputSection *Sec = CreateSection (Name, 0 );
453
465
std::vector<Chunk *> &Chunks = Pair.second ;
454
466
for (Chunk *C : Chunks) {
455
467
Sec->addChunk (C);
@@ -838,9 +850,9 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
838
850
// Write data directory
839
851
auto *Dir = reinterpret_cast <data_directory *>(Buf);
840
852
Buf += sizeof (*Dir) * NumberfOfDataDirectory;
841
- if (EdataSec-> getVirtualSize ()) {
842
- Dir[EXPORT_TABLE].RelativeVirtualAddress = EdataSec-> getRVA ();
843
- Dir[EXPORT_TABLE].Size = EdataSec-> getVirtualSize ();
853
+ if (!Config-> Exports . empty ()) {
854
+ Dir[EXPORT_TABLE].RelativeVirtualAddress = Edata. getRVA ();
855
+ Dir[EXPORT_TABLE].Size = Edata. getSize ();
844
856
}
845
857
if (!Idata.empty ()) {
846
858
Dir[IMPORT_TABLE].RelativeVirtualAddress = Idata.getDirRVA ();
@@ -852,9 +864,10 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
852
864
Dir[RESOURCE_TABLE].RelativeVirtualAddress = RsrcSec->getRVA ();
853
865
Dir[RESOURCE_TABLE].Size = RsrcSec->getVirtualSize ();
854
866
}
855
- if (PdataSec->getVirtualSize ()) {
856
- Dir[EXCEPTION_TABLE].RelativeVirtualAddress = PdataSec->getRVA ();
857
- Dir[EXCEPTION_TABLE].Size = PdataSec->getVirtualSize ();
867
+ if (FirstPdata) {
868
+ Dir[EXCEPTION_TABLE].RelativeVirtualAddress = FirstPdata->getRVA ();
869
+ Dir[EXCEPTION_TABLE].Size =
870
+ LastPdata->getRVA () + LastPdata->getSize () - FirstPdata->getRVA ();
858
871
}
859
872
if (RelocSec->getVirtualSize ()) {
860
873
Dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = RelocSec->getRVA ();
@@ -1159,11 +1172,15 @@ void Writer::writeBuildId() {
1159
1172
1160
1173
// Sort .pdata section contents according to PE/COFF spec 5.5.
1161
1174
void Writer::sortExceptionTable () {
1162
- if (PdataSec-> getVirtualSize () == 0 )
1175
+ if (!FirstPdata )
1163
1176
return ;
1164
1177
// We assume .pdata contains function table entries only.
1165
- uint8_t *Begin = Buffer->getBufferStart () + PdataSec->getFileOff ();
1166
- uint8_t *End = Begin + PdataSec->getVirtualSize ();
1178
+ auto BufAddr = [&](Chunk *C) {
1179
+ return Buffer->getBufferStart () + C->getOutputSection ()->getFileOff () +
1180
+ C->getRVA () - C->getOutputSection ()->getRVA ();
1181
+ };
1182
+ uint8_t *Begin = BufAddr (FirstPdata);
1183
+ uint8_t *End = BufAddr (LastPdata) + LastPdata->getSize ();
1167
1184
if (Config->Machine == AMD64) {
1168
1185
struct Entry { ulittle32_t Begin, End, Unwind; };
1169
1186
sort (parallel::par, (Entry *)Begin, (Entry *)End,
0 commit comments