Index: include/lld/Core/DefinedAtom.h =================================================================== --- include/lld/Core/DefinedAtom.h +++ include/lld/Core/DefinedAtom.h @@ -234,6 +234,13 @@ /// For a function atom, it is the number of bytes of code in the function. virtual uint64_t size() const = 0; + /// \brief The size of the section from which the atom is instantiated. + /// + /// Merge::mergeByLargestSection is defined in terms of section size + /// and not in terms of atom size, so we need this function separate + /// from size(). + virtual uint64_t sectionSize() const { return 0; } + /// \brief The visibility of this atom to other atoms. /// /// C static functions have scope scopeTranslationUnit. Regular C functions Index: lib/Core/SymbolTable.cpp =================================================================== --- lib/Core/SymbolTable.cpp +++ lib/Core/SymbolTable.cpp @@ -133,36 +133,6 @@ return mergeCases[first][second]; } -static const DefinedAtom *followReference(const DefinedAtom *atom, - uint32_t kind) { - for (const Reference *r : *atom) - if (r->kindNamespace() == Reference::KindNamespace::all && - r->kindArch() == Reference::KindArch::all && - r->kindValue() == kind) - return cast(r->target()); - return nullptr; -} - -static uint64_t getSizeFollowReferences(const DefinedAtom *atom, - uint32_t kind) { - uint64_t size = 0; - for (;;) { - atom = followReference(atom, kind); - if (!atom) - return size; - size += atom->size(); - } -} - -// Returns the size of the section containing the given atom. Atoms in the same -// section are connected by layout-before and layout-after edges, so this -// function traverses them to get the total size of atoms in the same section. -static uint64_t sectionSize(const DefinedAtom *atom) { - return atom->size() - + getSizeFollowReferences(atom, lld::Reference::kindLayoutBefore) - + getSizeFollowReferences(atom, lld::Reference::kindLayoutAfter); -} - bool SymbolTable::addByName(const Atom &newAtom) { StringRef name = newAtom.name(); assert(!name.empty()); @@ -198,14 +168,14 @@ useNew = true; break; case MCR_Largest: { - uint64_t existingSize = sectionSize(existingDef); - uint64_t newSize = sectionSize(newDef); + uint64_t existingSize = existingDef->sectionSize(); + uint64_t newSize = newDef->sectionSize(); useNew = (newSize >= existingSize); break; } case MCR_SameSize: { - uint64_t existingSize = sectionSize(existingDef); - uint64_t newSize = sectionSize(newDef); + uint64_t existingSize = existingDef->sectionSize(); + uint64_t newSize = newDef->sectionSize(); if (existingSize == newSize) { useNew = true; break; Index: lib/ReaderWriter/Native/NativeFileFormat.h =================================================================== --- lib/ReaderWriter/Native/NativeFileFormat.h +++ lib/ReaderWriter/Native/NativeFileFormat.h @@ -136,6 +136,7 @@ uint32_t referencesCount; uint32_t contentOffset; uint32_t contentSize; + uint64_t sectionSize; }; Index: lib/ReaderWriter/Native/ReaderNative.cpp =================================================================== --- lib/ReaderWriter/Native/ReaderNative.cpp +++ lib/ReaderWriter/Native/ReaderNative.cpp @@ -45,9 +45,8 @@ StringRef name() const override; - uint64_t size() const override { - return _ivarData->contentSize; - } + uint64_t size() const override { return _ivarData->contentSize; } + uint64_t sectionSize() const override { return _ivarData->sectionSize; } DefinedAtom::Scope scope() const override { return (DefinedAtom::Scope)(attributes().scope); Index: lib/ReaderWriter/Native/WriterNative.cpp =================================================================== --- lib/ReaderWriter/Native/WriterNative.cpp +++ lib/ReaderWriter/Native/WriterNative.cpp @@ -126,6 +126,7 @@ ivar.referencesCount = refsCount; ivar.contentOffset = getContentOffset(atom); ivar.contentSize = atom.size(); + ivar.sectionSize = atom.sectionSize(); _definedAtomIvars.push_back(ivar); } Index: lib/ReaderWriter/PECOFF/Atoms.h =================================================================== --- lib/ReaderWriter/PECOFF/Atoms.h +++ lib/ReaderWriter/PECOFF/Atoms.h @@ -145,11 +145,12 @@ class COFFDefinedFileAtom : public COFFBaseDefinedAtom { public: COFFDefinedFileAtom(const File &file, StringRef name, StringRef sectionName, - Scope scope, ContentType contentType, - ContentPermissions perms, uint64_t ordinal) + uint64_t sectionSize, Scope scope, + ContentType contentType, ContentPermissions perms, + uint64_t ordinal) : COFFBaseDefinedAtom(file, name, Kind::File), _sectionName(sectionName), - _scope(scope), _contentType(contentType), _permissions(perms), - _ordinal(ordinal), _alignment(0) {} + _sectionSize(sectionSize), _scope(scope), _contentType(contentType), + _permissions(perms), _ordinal(ordinal), _alignment(0) {} static bool classof(const COFFBaseDefinedAtom *atom) { return atom->getKind() == Kind::File; @@ -158,6 +159,7 @@ void setAlignment(Alignment val) { _alignment = val; } SectionChoice sectionChoice() const override { return sectionCustomRequired; } StringRef customSectionName() const override { return _sectionName; } + uint64_t sectionSize() const override { return _sectionSize; } Scope scope() const override { return _scope; } ContentType contentType() const override { return _contentType; } ContentPermissions permissions() const override { return _permissions; } @@ -173,6 +175,7 @@ private: StringRef _sectionName; + uint64_t _sectionSize; Scope _scope; ContentType _contentType; ContentPermissions _permissions; @@ -185,11 +188,11 @@ class COFFDefinedAtom : public COFFDefinedFileAtom { public: COFFDefinedAtom(const File &file, StringRef name, StringRef sectionName, - Scope scope, ContentType type, bool isComdat, - ContentPermissions perms, Merge merge, ArrayRef data, - uint64_t ordinal) - : COFFDefinedFileAtom(file, name, sectionName, scope, type, perms, - ordinal), + uint64_t sectionSize, Scope scope, ContentType type, + bool isComdat, ContentPermissions perms, Merge merge, + ArrayRef data, uint64_t ordinal) + : COFFDefinedFileAtom(file, name, sectionName, sectionSize, + scope, type, perms, ordinal), _isComdat(isComdat), _merge(merge), _dataref(data) {} Merge merge() const override { return _merge; } @@ -213,8 +216,8 @@ COFFBSSAtom(const File &file, StringRef name, Scope scope, ContentPermissions perms, Merge merge, uint32_t size, uint64_t ordinal) - : COFFDefinedFileAtom(file, name, ".bss", scope, typeZeroFill, perms, - ordinal), + : COFFDefinedFileAtom(file, name, ".bss", 0, scope, typeZeroFill, + perms, ordinal), _merge(merge), _size(size) {} Merge merge() const override { return _merge; } Index: lib/ReaderWriter/PECOFF/ReaderCOFF.cpp =================================================================== --- lib/ReaderWriter/PECOFF/ReaderCOFF.cpp +++ lib/ReaderWriter/PECOFF/ReaderCOFF.cpp @@ -694,14 +694,15 @@ DefinedAtom::ContentType type = getContentType(section); DefinedAtom::ContentPermissions perms = getPermissions(section); + uint64_t sectionSize = section->SizeOfRawData; bool isComdat = (_comdatSections.count(section) == 1); // Create an atom for the entire section. if (symbols.empty()) { ArrayRef data(secData.data(), secData.size()); auto *atom = new (_alloc) COFFDefinedAtom( - *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat, - perms, _merge[section], data, getNextOrdinal()); + *this, "", sectionName, sectionSize, Atom::scopeTranslationUnit, + type, isComdat, perms, _merge[section], data, getNextOrdinal()); atoms.push_back(atom); _definedAtomLocations[section][0].push_back(atom); return std::error_code(); @@ -713,8 +714,8 @@ uint64_t size = symbols[0].getValue(); ArrayRef data(secData.data(), size); auto *atom = new (_alloc) COFFDefinedAtom( - *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat, - perms, _merge[section], data, getNextOrdinal()); + *this, "", sectionName, sectionSize, Atom::scopeTranslationUnit, + type, isComdat, perms, _merge[section], data, getNextOrdinal()); atoms.push_back(atom); _definedAtomLocations[section][0].push_back(atom); } @@ -726,8 +727,8 @@ : secData.data() + (si + 1)->getValue(); ArrayRef data(start, end); auto *atom = new (_alloc) COFFDefinedAtom( - *this, _symbolName[*si], sectionName, getScope(*si), type, isComdat, - perms, _merge[section], data, getNextOrdinal()); + *this, _symbolName[*si], sectionName, sectionSize, getScope(*si), + type, isComdat, perms, _merge[section], data, getNextOrdinal()); atoms.push_back(atom); _symbolAtom[*si] = atom; _definedAtomLocations[section][si->getValue()].push_back(atom); @@ -982,9 +983,9 @@ return std::error_code(); auto *atom = new (_alloc) COFFDefinedAtom( - *this, "", ".sxdata", Atom::scopeTranslationUnit, DefinedAtom::typeData, - false /*isComdat*/, DefinedAtom::permR__, DefinedAtom::mergeNo, - sxdata, getNextOrdinal()); + *this, "", ".sxdata", 0, Atom::scopeTranslationUnit, + DefinedAtom::typeData, false /*isComdat*/, DefinedAtom::permR__, + DefinedAtom::mergeNo, sxdata, getNextOrdinal()); const ulittle32_t *symbolIndex = reinterpret_cast(sxdata.data()); Index: lib/ReaderWriter/YAML/ReaderWriterYAML.cpp =================================================================== --- lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -814,7 +814,8 @@ _deadStrip(atom->deadStrip()), _dynamicExport(atom->dynamicExport()), _codeModel(atom->codeModel()), _permissions(atom->permissions()), _size(atom->size()), - _sectionName(atom->customSectionName()) { + _sectionName(atom->customSectionName()), + _sectionSize(atom->sectionSize()) { for (const lld::Reference *r : *atom) _references.push_back(r); if (!atom->occupiesDiskSpace()) @@ -860,6 +861,7 @@ Alignment alignment() const override { return _alignment; } SectionChoice sectionChoice() const override { return _sectionChoice; } StringRef customSectionName() const override { return _sectionName; } + uint64_t sectionSize() const override { return _sectionSize; } SectionPosition sectionPosition() const override { return _sectionPosition; } DeadStripKind deadStrip() const override { return _deadStrip; } DynamicExport dynamicExport() const override { return _dynamicExport; } @@ -915,6 +917,7 @@ std::vector _content; uint64_t _size; StringRef _sectionName; + uint64_t _sectionSize; std::vector _references; bool _isGroupChild; }; @@ -953,6 +956,7 @@ io.mapOptional("section-name", keys->_sectionName, StringRef()); io.mapOptional("section-position", keys->_sectionPosition, DefinedAtom::sectionPositionAny); + io.mapOptional("section-size", keys->_sectionSize, (uint64_t)0); io.mapOptional("dead-strip", keys->_deadStrip, DefinedAtom::deadStripNormal); io.mapOptional("dynamic-export", keys->_dynamicExport, Index: test/pecoff/Inputs/merge-same-size3.obj.yaml =================================================================== --- test/pecoff/Inputs/merge-same-size3.obj.yaml +++ test/pecoff/Inputs/merge-same-size3.obj.yaml @@ -15,7 +15,7 @@ ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_STATIC SectionDefinition: - Length: 7 + Length: 2 NumberOfRelocations: 0 NumberOfLinenumbers: 0 CheckSum: 2532800969