Skip to content

Commit 11e93ea

Browse files
[LLD][COFF] Deduplicate common chunks when linking COFF files.
This fixes issue 162148. Common symbols are intended to have only a single version of the data present in the final executable. The MSVC linker is able to successfully deduplicate these chunks. If you have an application with a large number of translation units with a large block of common data (this is possible, for example, with Fortran code), then failing to deduplicate these chunks can make the data size so large that the resulting executable fails to load. The logic in this patch doesn't catch all of the potential cases for deduplication, but it should catch the most common ones.
1 parent 4564ac9 commit 11e93ea

File tree

4 files changed

+9
-1
lines changed

4 files changed

+9
-1
lines changed

lld/COFF/Chunks.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ uint32_t SectionChunk::getSectionNumber() const {
773773
return s.getIndex() + 1;
774774
}
775775

776-
CommonChunk::CommonChunk(const COFFSymbolRef s) : sym(s) {
776+
CommonChunk::CommonChunk(const COFFSymbolRef s) : active(false), sym(s) {
777777
// The value of a common symbol is its size. Align all common symbols smaller
778778
// than 32 bytes naturally, i.e. round the size up to the next power of two.
779779
// This is what MSVC link.exe does.

lld/COFF/Chunks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,8 @@ class CommonChunk : public NonSectionChunk {
520520
uint32_t getOutputCharacteristics() const override;
521521
StringRef getSectionName() const override { return ".bss"; }
522522

523+
bool active;
524+
523525
private:
524526
const COFFSymbolRef sym;
525527
};

lld/COFF/Symbols.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ class DefinedCommon : public DefinedCOFF {
233233
CommonChunk *c = nullptr)
234234
: DefinedCOFF(DefinedCommonKind, f, n, s), data(c), size(size) {
235235
this->isExternal = true;
236+
if (c)
237+
c->active = true;
236238
}
237239

238240
static bool classof(const Symbol *s) {

lld/COFF/Writer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,10 @@ void Writer::createSections() {
10931093
sc->printDiscardedMessage();
10941094
continue;
10951095
}
1096+
if (auto *cc = dyn_cast<CommonChunk>(c)) {
1097+
if (!cc->active)
1098+
continue;
1099+
}
10961100
StringRef name = c->getSectionName();
10971101
if (shouldStripSectionSuffix(sc, name, ctx.config.mingw))
10981102
name = name.split('$').first;

0 commit comments

Comments
 (0)