Index: lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp +++ lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp @@ -118,13 +118,23 @@ uint64_t lastVirtualAddress = 0; this->setFileOffset(startOffset); + bool changeOffset = false; + uint64_t newOffset = 0; for (auto &slice : slices()) { bool isFirstSection = true; for (auto section : slice->sections()) { // Handle linker script expressions, which may change the offset - if (!isFirstSection) - if (auto expr = dyn_cast>(section)) - fileOffset += expr->virtualAddr() - lastVirtualAddress; + if (auto expr = dyn_cast>(section)) { + if (!isFirstSection) { + changeOffset = true; + newOffset = fileOffset + expr->virtualAddr() - lastVirtualAddress; + } + continue; + } + if (changeOffset) { + changeOffset = false; + fileOffset = newOffset; + } // Align fileoffset to the alignment of the section. fileOffset = llvm::RoundUpToAlignment(fileOffset, section->alignment()); // If the linker outputmagic is set to OutputMagic::NMAGIC, align the Data @@ -136,17 +146,14 @@ // OutputMagic::NMAGIC/OutputMagic::OMAGIC if (alignSegments) fileOffset = llvm::RoundUpToAlignment(fileOffset, p_align); - else { - // Align according to ELF spec. - // in p75, http://www.sco.com/developers/devspecs/gabi41.pdf - uint64_t virtualAddress = slice->virtualAddr(); - Section *sect = dyn_cast>(section); - if (sect && sect->isLoadableSection() && - ((virtualAddress & (p_align - 1)) != - (fileOffset & (p_align - 1)))) - fileOffset = llvm::RoundUpToAlignment(fileOffset, p_align) + - (virtualAddress % p_align); - } + // Align according to ELF spec. + // in p75, http://www.sco.com/developers/devspecs/gabi41.pdf + uint64_t virtualAddress = slice->virtualAddr(); + Section *sect = dyn_cast>(section); + if (sect && sect->isLoadableSection() && + ((virtualAddress & (p_align - 1)) != (fileOffset & (p_align - 1)))) + fileOffset = llvm::RoundUpToAlignment(fileOffset, p_align) + + (virtualAddress % p_align); } else if (!isDataPageAlignedForNMagic && needAlign(section)) { fileOffset = llvm::RoundUpToAlignment(fileOffset, this->_ctx.getPageSize()); @@ -161,6 +168,7 @@ fileOffset += section->fileSize(); lastVirtualAddress = section->virtualAddr() + section->memSize(); } + changeOffset = false; slice->setFileSize(fileOffset - curSliceFileOffset); } this->setFileSize(fileOffset - startOffset); @@ -242,6 +250,8 @@ ++si; } + uint64_t scriptAddr = 0; + bool forceScriptAddr = false; for (auto e = _sections.end(); si != e; ++si) { uint64_t curAddr = curSliceAddress + curSliceSize; if (!isDataPageAlignedForNMagic && needAlign(*si)) { @@ -251,23 +261,25 @@ curAddr = llvm::RoundUpToAlignment(curAddr, this->_ctx.getPageSize()); isDataPageAlignedForNMagic = true; } - uint64_t newAddr = llvm::RoundUpToAlignment(curAddr, (*si)->alignment()); - // Handle linker script expressions, which *may update newAddr* if the - // expression assigns to "." - if (auto expr = dyn_cast>(*si)) + uint64_t newAddr = llvm::RoundUpToAlignment( + forceScriptAddr ? scriptAddr : curAddr, (*si)->alignment()); + forceScriptAddr = false; + + // Handle linker script expressions, which may force an address change if + // the expression assigns to "." + if (auto expr = dyn_cast>(*si)) { + uint64_t oldAddr = newAddr; expr->evalExpr(newAddr); - Section *sec = dyn_cast>(*si); - StringRef curOutputSectionName; - if (sec) { - curOutputSectionName = sec->outputSectionName(); - } else { - // If this is a linker script expression, propagate the name of the - // previous section instead - if (isa>(*si)) - curOutputSectionName = prevOutputSectionName; - else - curOutputSectionName = (*si)->name(); + if (oldAddr != newAddr) { + forceScriptAddr = true; + scriptAddr = newAddr; + } + (*si)->setVirtualAddr(newAddr); + continue; } + Section *sec = dyn_cast>(*si); + StringRef curOutputSectionName = + sec ? sec->outputSectionName() : (*si)->name(); bool autoCreateSlice = true; if (curOutputSectionName == prevOutputSectionName) autoCreateSlice = false; Index: lld/trunk/test/elf/linkerscript/sections-order.test =================================================================== --- lld/trunk/test/elf/linkerscript/sections-order.test +++ lld/trunk/test/elf/linkerscript/sections-order.test @@ -94,4 +94,20 @@ CHECKSYMS: Name: prog2 CHECKSYMS-NEXT: Value: 0x506050 + +RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix CHECKPHDRS %s + +CHECKPHDRS: Type: PT_LOAD (0x1) +CHECKPHDRS: Offset: 0x1000 +CHECKPHDRS-NEXT: VirtualAddress: 0x500000 +CHECKPHDRS-NEXT: PhysicalAddress: 0x500000 +CHECKPHDRS-NEXT: FileSize: 48 +CHECKPHDRS-NEXT: MemSize: 48 + +CHECKPHDRS: Type: PT_LOAD (0x1) +CHECKPHDRS: Offset: 0x2030 +CHECKPHDRS-NEXT: VirtualAddress: 0x506030 +CHECKPHDRS-NEXT: PhysicalAddress: 0x506030 +CHECKPHDRS-NEXT: FileSize: 168 +CHECKPHDRS-NEXT: MemSize: 168 */