diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -810,7 +810,7 @@ // is acceptable because section merging is optional. if (auto *ms = dyn_cast(s)) { s = makeThreadLocal( - ms->file, ms->flags, ms->type, ms->addralign, + ms->file, ms->flags, ms->type, ms->addralign.value(), ms->contentMaybeDecompress(), ms->name); sections[info] = s; } diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -71,7 +71,7 @@ // These corresponds to the fields in Elf_Shdr. uint64_t flags; - uint32_t addralign; + llvm::Align addralign; uint32_t entsize; uint32_t link; uint32_t info; @@ -93,7 +93,7 @@ protected: constexpr SectionBase(Kind sectionKind, StringRef name, uint64_t flags, - uint32_t entsize, uint32_t addralign, uint32_t type, + uint32_t entsize, llvm::Align addralign, uint32_t type, uint32_t info, uint32_t link) : sectionKind(sectionKind), bss(false), keepUnique(false), type(type), name(name), flags(flags), addralign(addralign), entsize(entsize), diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -53,22 +53,22 @@ uint32_t link, uint32_t info, uint32_t addralign, ArrayRef data, StringRef name, Kind sectionKind) - : SectionBase(sectionKind, name, flags, entsize, addralign, type, info, - link), + : SectionBase(sectionKind, name, flags, entsize, + /*overrode below after validation*/ llvm::Align(1), type, + info, link), file(file), content_(data.data()), size(data.size()) { + // The ELF spec states that a value of 0 means the section has + // no alignment constraints. + if (addralign != 0 && !isPowerOf2_64(addralign)) + fatal(toString(this) + ": sh_addralign is not a power of 2"); + this->addralign = llvm::MaybeAlign(addralign).valueOrOne(); + // In order to reduce memory allocation, we assume that mergeable // sections are smaller than 4 GiB, which is not an unreasonable // assumption as of 2017. if (sectionKind == SectionBase::Merge && content().size() > UINT32_MAX) error(toString(this) + ": section too large"); - // The ELF spec states that a value of 0 means the section has - // no alignment constraints. - uint32_t v = std::max(addralign, 1); - if (!isPowerOf2_64(v)) - fatal(toString(this) + ": sh_addralign is not a power of 2"); - this->addralign = v; - // If SHF_COMPRESSED is set, parse the header. The legacy .zdebug format is no // longer supported. if (flags & SHF_COMPRESSED) @@ -231,7 +231,7 @@ compressed = true; compressedSize = size; size = hdr->ch_size; - addralign = std::max(hdr->ch_addralign, 1); + addralign = llvm::MaybeAlign(hdr->ch_addralign).valueOrOne(); } InputSection *InputSectionBase::getLinkOrderDep() const { diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -44,6 +44,7 @@ bool isAbsolute() const { return forceAbsolute || sec == nullptr; } uint64_t getValue() const; + llvm::Align getValueAsAlign() const { return llvm::Align(getValue()); } uint64_t getSecAddr() const; uint64_t getSectionOffset() const; diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -631,7 +631,7 @@ // is given, input sections are aligned to that value, whether the // given value is larger or smaller than the original section alignment. if (osec->subalignExpr) { - uint32_t subalign = osec->subalignExpr().getValue(); + llvm::Align subalign = osec->subalignExpr().getValueAsAlign(); for (InputSectionBase *s : v) s->addralign = subalign; } @@ -996,7 +996,7 @@ // sec->alignment is the max of ALIGN and the maximum of input // section alignments. const uint64_t pos = dot; - dot = alignToPowerOf2(dot, sec->addralign); + dot = alignTo(dot, sec->addralign); sec->addr = dot; expandMemoryRegions(dot - pos); } @@ -1010,7 +1010,7 @@ if (sec->lmaExpr) { state->lmaOffset = sec->lmaExpr().getValue() - dot; } else if (MemoryRegion *mr = sec->lmaRegion) { - uint64_t lmaStart = alignToPowerOf2(mr->curPos, sec->addralign); + uint64_t lmaStart = alignTo(mr->curPos, sec->addralign); if (mr->curPos < lmaStart) expandMemoryRegion(mr, lmaStart - mr->curPos, sec->name); state->lmaOffset = lmaStart - dot; @@ -1053,7 +1053,7 @@ for (InputSection *isec : cast(cmd)->sections) { assert(isec->getParent() == sec); const uint64_t pos = dot; - dot = alignToPowerOf2(dot, isec->addralign); + dot = alignTo(dot, isec->addralign); isec->outSecOff = dot - sec->addr; dot += isec->getSize(); @@ -1153,7 +1153,7 @@ // Handle align (e.g. ".foo : ALIGN(16) { ... }"). if (sec->alignExpr) sec->addralign = - std::max(sec->addralign, sec->alignExpr().getValue()); + std::max(sec->addralign, sec->alignExpr().getValueAsAlign()); bool isEmpty = (getFirstInputSection(sec) == nullptr); bool discardable = isEmpty && isDiscardable(*sec); diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -169,7 +169,8 @@ } osec = &cast(cmd)->osec; - writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->addralign); + writeHeader(os, osec->addr, osec->getLMA(), osec->size, + osec->addralign.value()); os << osec->name << '\n'; // Dump symbols for each input section. @@ -182,7 +183,7 @@ } writeHeader(os, isec->getVA(), osec->getLMA() + isec->outSecOff, - isec->getSize(), isec->addralign); + isec->getSize(), isec->addralign.value()); os << indent8 << toString(isec) << '\n'; for (Symbol *sym : llvm::make_first_range(sectionSyms[isec])) os << symStr[sym] << '\n'; diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -60,7 +60,7 @@ template void OutputSection::writeHeaderTo(typename ELFT::Shdr *shdr) { shdr->sh_entsize = entsize; - shdr->sh_addralign = addralign; + shdr->sh_addralign = addralign.value(); shdr->sh_type = type; shdr->sh_offset = offset; shdr->sh_flags = flags; @@ -72,7 +72,7 @@ } OutputSection::OutputSection(StringRef name, uint32_t type, uint64_t flags) - : SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type, + : SectionBase(Output, name, flags, /*Entsize*/ 0, llvm::Align(1), type, /*Info*/ 0, /*Link*/ 0) {} // We allow sections of types listed below to merged into a @@ -216,8 +216,8 @@ (sec->addralign == ms->addralign || !(sec->flags & SHF_STRINGS)); }); if (i == mergeSections.end()) { - MergeSyntheticSection *syn = - createMergeSynthetic(name, ms->type, ms->flags, ms->addralign); + MergeSyntheticSection *syn = createMergeSynthetic( + name, ms->type, ms->flags, ms->addralign.value()); mergeSections.push_back(syn); i = std::prev(mergeSections.end()); syn->entsize = ms->entsize; @@ -452,7 +452,7 @@ if (compressed.shards) { auto *chdr = reinterpret_cast(buf); chdr->ch_size = compressed.uncompressedSize; - chdr->ch_addralign = addralign; + chdr->ch_addralign = addralign.value(); buf += sizeof(*chdr); if (config->compressDebugSections == DebugCompressionType::Zstd) { chdr->ch_type = ELFCOMPRESS_ZSTD; diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -1408,7 +1408,7 @@ OutputSection *osec = &script->getOrCreateOutputSection(name)->osec; return [=] { checkIfExists(*osec, location); - return osec->addralign; + return osec->addralign.value(); }; } if (tok == "ASSERT") diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -890,7 +890,7 @@ for (SectionCommand *cmd : os->commands) { if (auto *isd = dyn_cast(cmd)) for (InputSection *isec : isd->sections) { - uint64_t off = alignToPowerOf2(secSize, isec->addralign); + uint64_t off = alignTo(secSize, isec->addralign); secSize = off + isec->getSize(); } } @@ -2203,7 +2203,7 @@ // When -r is specified, a COMMON symbol is not allocated. Its st_shndx // holds SHN_COMMON and st_value holds the alignment. eSym->st_shndx = SHN_COMMON; - eSym->st_value = commonSec->addralign; + eSym->st_value = commonSec->addralign.value(); eSym->st_size = cast(sym)->size; } else { const uint32_t shndx = getSymSectionIndex(sym); @@ -2484,7 +2484,7 @@ // On PowerPC, this section contains lazy symbol resolvers. if (config->emachine == EM_PPC64) { name = ".glink"; - addralign = 4; + addralign = llvm::Align(4); } // On x86 when IBT is enabled, this section contains the second PLT (lazy @@ -2542,7 +2542,7 @@ : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".iplt") { if (config->emachine == EM_PPC || config->emachine == EM_PPC64) { name = ".glink"; - addralign = 4; + addralign = llvm::Align(4); } } @@ -2575,7 +2575,7 @@ PPC32GlinkSection::PPC32GlinkSection() { name = ".glink"; - addralign = 4; + addralign = llvm::Align(4); } void PPC32GlinkSection::writeTo(uint8_t *buf) { @@ -3277,7 +3277,7 @@ for (size_t i = 0; i < numShards; ++i) { shards[i].finalizeInOrder(); if (shards[i].getSize() > 0) - off = alignToPowerOf2(off, addralign); + off = alignTo(off, addralign); shardOffsets[i] = off; off += shards[i].getSize(); } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -282,7 +282,7 @@ in.shStrTab = std::make_unique(".shstrtab", false); Out::programHeaders = make("", 0, SHF_ALLOC); - Out::programHeaders->addralign = config->wordsize; + Out::programHeaders->addralign = llvm::Align(config->wordsize); if (config->strip != StripPolicy::All) { in.strTab = std::make_unique(".strtab", false); @@ -992,7 +992,7 @@ lastSec = sec; if (!firstSec) firstSec = sec; - p_align = std::max(p_align, sec->addralign); + p_align = std::max(p_align, (uint32_t)sec->addralign.value()); if (p_type == PT_LOAD) sec->ptLoad = this; } @@ -1684,10 +1684,10 @@ for (SectionCommand *cmd : script->sectionCommands) if (auto *osd = dyn_cast(cmd)) { OutputSection *osec = &osd->osec; - if (osec->addr % osec->addralign != 0) + if (!isAligned(osec->addralign, osec->addr)) warn("address (0x" + Twine::utohexstr(osec->addr) + ") of section " + osec->name + " is not a multiple of alignment (" + - Twine(osec->addralign) + ")"); + Twine(osec->addralign.value()) + ")"); } } @@ -2436,7 +2436,7 @@ OutputSection *cmd = p->firstSec; if (!cmd) return; - cmd->alignExpr = [align = cmd->addralign]() { return align; }; + cmd->alignExpr = [align = cmd->addralign]() { return align.value(); }; if (!cmd->addrExpr) { // Prefer advancing to align(dot, maxPageSize) + dot%maxPageSize to avoid // padding in the file contents. @@ -2513,7 +2513,7 @@ // If the section is not in a PT_LOAD, we just have to align it. if (!os->ptLoad) - return alignToPowerOf2(off, os->addralign); + return alignTo(off, os->addralign); // If two sections share the same PT_LOAD the file offset is calculated // using this formula: Off2 = Off1 + (VA2 - VA1). @@ -2576,7 +2576,7 @@ } for (OutputSection *osec : outputSections) if (!(osec->flags & SHF_ALLOC)) { - osec->offset = alignToPowerOf2(off, osec->addralign); + osec->offset = alignTo(off, osec->addralign); off = osec->offset + osec->size; }