Skip to content

Commit 64f6c57

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 a1c09a9 commit 64f6c57

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
@@ -777,7 +777,7 @@ uint32_t SectionChunk::getSectionNumber() const {
777777
return s.getIndex() + 1;
778778
}
779779

780-
CommonChunk::CommonChunk(const COFFSymbolRef s) : sym(s) {
780+
CommonChunk::CommonChunk(const COFFSymbolRef s) : active(false), sym(s) {
781781
// The value of a common symbol is its size. Align all common symbols smaller
782782
// than 32 bytes naturally, i.e. round the size up to the next power of two.
783783
// 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
@@ -522,6 +522,8 @@ class CommonChunk : public NonSectionChunk {
522522
uint32_t getOutputCharacteristics() const override;
523523
StringRef getSectionName() const override { return ".bss"; }
524524

525+
bool active;
526+
525527
private:
526528
const COFFSymbolRef sym;
527529
};

lld/COFF/Symbols.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ class DefinedCommon : public DefinedCOFF {
236236
CommonChunk *c = nullptr)
237237
: DefinedCOFF(DefinedCommonKind, f, n, s), data(c), size(size) {
238238
this->isExternal = true;
239+
if (c)
240+
c->active = true;
239241
}
240242

241243
static bool classof(const Symbol *s) {

lld/COFF/Writer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,10 @@ void Writer::createSections() {
11141114
sc->printDiscardedMessage();
11151115
continue;
11161116
}
1117+
if (auto *cc = dyn_cast<CommonChunk>(c)) {
1118+
if (!cc->active)
1119+
continue;
1120+
}
11171121
StringRef name = c->getSectionName();
11181122
if (shouldStripSectionSuffix(sc, name, ctx.config.mingw))
11191123
name = name.split('$').first;

0 commit comments

Comments
 (0)