From 294cca1e8c3008a6ceb15b1989be9d6a6186fa78 Mon Sep 17 00:00:00 2001 From: Shankar Easwaran Date: Wed, 19 Nov 2014 03:51:48 +0000 Subject: [PATCH] [ELF] Fix creation of segments. Linker was creating a separate output segment in some cases if input sections had huge alignments. This patch fixes the issue. llvm-svn: 222312 --- lld/lib/ReaderWriter/ELF/SegmentChunks.h | 18 ++- lld/test/elf/X86_64/alignoffset.test | 2 +- lld/test/elf/X86_64/outputsegments.test | 189 +++++++++++++++++++++++ lld/test/elf/phdr.test | 2 +- 4 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 lld/test/elf/X86_64/outputsegments.test diff --git a/lld/lib/ReaderWriter/ELF/SegmentChunks.h b/lld/lib/ReaderWriter/ELF/SegmentChunks.h index 62677611f7ea..fd81cf4e2d2c 100644 --- a/lld/lib/ReaderWriter/ELF/SegmentChunks.h +++ b/lld/lib/ReaderWriter/ELF/SegmentChunks.h @@ -406,6 +406,8 @@ void Segment::assignFileOffsets(uint64_t startOffset) { for (auto &slice : slices()) { bool isFirstSection = true; for (auto section : slice->sections()) { + // Align fileoffset to the alignment of the section. + fileOffset = llvm::RoundUpToAlignment(fileOffset, section->align2()); // If the linker outputmagic is set to OutputMagic::NMAGIC, align the Data // to a page boundary if (isFirstSection && @@ -430,8 +432,7 @@ void Segment::assignFileOffsets(uint64_t startOffset) { fileOffset = llvm::RoundUpToAlignment(fileOffset, this->_context.getPageSize()); isDataPageAlignedForNMagic = true; - } else - fileOffset = llvm::RoundUpToAlignment(fileOffset, section->align2()); + } if (isFirstSection) { slice->setFileOffset(fileOffset); isFirstSection = false; @@ -467,6 +468,7 @@ template void Segment::assignVirtualAddress(uint64_t addr) { SegmentSlice *slice = nullptr; uint64_t tlsStartAddr = 0; bool alignSegments = this->_context.alignSegments(); + StringRef prevOutputSectionName; for (auto si = _sections.begin(); si != _sections.end(); ++si) { // If this is first section in the segment, page align the section start @@ -522,9 +524,18 @@ template void Segment::assignVirtualAddress(uint64_t addr) { isDataPageAlignedForNMagic = true; } uint64_t newAddr = llvm::RoundUpToAlignment(curAddr, (*si)->align2()); + Section *sec = dyn_cast>(*si); + StringRef curOutputSectionName = + sec ? sec->outputSectionName() : (*si)->name(); + bool autoCreateSlice = true; + if (curOutputSectionName == prevOutputSectionName) + autoCreateSlice = false; // If the newAddress computed is more than a page away, let's create // a separate segment, so that memory is not used up while running. - if (((newAddr - curAddr) > this->_context.getPageSize()) && + // Dont create a slice, if the new section falls in the same output + // section as the previous section. + if (autoCreateSlice && + ((newAddr - curAddr) > this->_context.getPageSize()) && (_outputMagic != ELFLinkingContext::OutputMagic::NMAGIC && _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)) { auto sliceIter = @@ -577,6 +588,7 @@ template void Segment::assignVirtualAddress(uint64_t addr) { else curSliceSize = newAddr - curSliceAddress; } + prevOutputSectionName = curOutputSectionName; } currSection++; } diff --git a/lld/test/elf/X86_64/alignoffset.test b/lld/test/elf/X86_64/alignoffset.test index 031463e669ab..b061f8937935 100644 --- a/lld/test/elf/X86_64/alignoffset.test +++ b/lld/test/elf/X86_64/alignoffset.test @@ -7,7 +7,7 @@ # RUN: --no-align-segments --rosegment --noinhibit-exec # RUN: llvm-readobj -program-headers %t.exe | FileCheck %s # -#CHECK: Offset: 0x115C +#CHECK: Offset: 0x15C #CHECK: VirtualAddress: 0x40015C #CHECK: PhysicalAddress: 0x40015C # diff --git a/lld/test/elf/X86_64/outputsegments.test b/lld/test/elf/X86_64/outputsegments.test new file mode 100644 index 000000000000..125ac4ae408b --- /dev/null +++ b/lld/test/elf/X86_64/outputsegments.test @@ -0,0 +1,189 @@ +# Tests that lld doesnot create separate segment if the input sections are part +# of the same output section + +# Build executable +# RUN: yaml2obj -format=elf -docnum 1 %s -o %t.o +# RUN: lld -flavor gnu -target x86_64 %t.o -o %t1.exe -static \ +# RUN: --no-align-segments --noinhibit-exec +# RUN: lld -flavor gnu -target x86_64 %t.o -o %t2.exe -static \ +# RUN: --noinhibit-exec +# RUN: llvm-readobj -program-headers %t1.exe | FileCheck %s -check-prefix=SEGMENTS +# RUN: llvm-readobj -program-headers %t2.exe | FileCheck %s -check-prefix=SEGMENTS +# +#SEGMENTS: VirtualAddress: 0x400000 +#SEGMENTS: PhysicalAddress: 0x400000 +#SEGMENTS: FileSize: 288 +#SEGMENTS: MemSize: 288 +#SEGMENTS: VirtualAddress: 0x404000 +#SEGMENTS: PhysicalAddress: 0x404000 +#SEGMENTS: FileSize: 16608 +#SEGMENTS: MemSize: 16608 +#SEGMENTS: Alignment: 16384 +# +# object +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_GNU + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .text.foo + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000002000 + Content: 554889E54883EC1048BF0000000000000000B000E800000000B9000000008945FC89C84883C4105DC3 + - Name: .rela.text.foo + Type: SHT_RELA + Link: .symtab + AddressAlign: 0x0000000000000008 + Info: .text.foo + Relocations: + - Offset: 0x000000000000000A + Symbol: .rodata.str1.1 + Type: R_X86_64_64 + Addend: 0 + - Offset: 0x0000000000000015 + Symbol: printf + Type: R_X86_64_PC32 + Addend: -4 + - Name: .text.bar + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000004000 + Content: 554889E54883EC1048BF0000000000000000B000E800000000B9000000008945FC89C84883C4105DC3 + - Name: .rela.text.bar + Type: SHT_RELA + Link: .symtab + AddressAlign: 0x0000000000000008 + Info: .text.bar + Relocations: + - Offset: 0x000000000000000A + Symbol: .rodata.str1.1 + Type: R_X86_64_64 + Addend: 7 + - Offset: 0x0000000000000015 + Symbol: printf + Type: R_X86_64_PC32 + Addend: -4 + - Name: .text.main + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000010 + Content: 554889E54883EC10C745FC00000000E8000000008945F8E8000000008B4DF801C189C84883C4105DC3 + - Name: .rela.text.main + Type: SHT_RELA + Link: .symtab + AddressAlign: 0x0000000000000008 + Info: .text.main + Relocations: + - Offset: 0x0000000000000010 + Symbol: foo + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x0000000000000018 + Symbol: bar + Type: R_X86_64_PC32 + Addend: -4 + - Name: .rodata.str1.1 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 48656C6C6F0A00576F726C640A00 + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 005562756E747520636C616E672076657273696F6E20332E352E302D73766E3231373330342D317E6578703120286272616E636865732F72656C656173655F33352920286261736564206F6E204C4C564D20332E352E302900 + - Name: .note.GNU-stack + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .eh_frame + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + AddressAlign: 0x0000000000000008 + Content: 1400000000000000037A5200017810011B0C070890010000180000001C000000000000002900000000410E108602430D060000001800000038000000000000002900000000410E108602430D060000001C00000054000000000000002900000000410E108602430D0600000000000000 + - Name: .rela.eh_frame + Type: SHT_RELA + Link: .symtab + AddressAlign: 0x0000000000000008 + Info: .eh_frame + Relocations: + - Offset: 0x0000000000000020 + Symbol: .text.foo + Type: R_X86_64_PC32 + Addend: 0 + - Offset: 0x000000000000003C + Symbol: .text.bar + Type: R_X86_64_PC32 + Addend: 0 + - Offset: 0x0000000000000058 + Symbol: .text.main + Type: R_X86_64_PC32 + Addend: 0 +Symbols: + Local: + - Name: 1.c + Type: STT_FILE + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .text.foo + Type: STT_SECTION + Section: .text.foo + - Name: .text.bar + Type: STT_SECTION + Section: .text.bar + - Name: .text.main + Type: STT_SECTION + Section: .text.main + - Name: .rodata.str1.1 + Type: STT_SECTION + Section: .rodata.str1.1 + - Name: .comment + Type: STT_SECTION + Section: .comment + - Name: .note.GNU-stack + Type: STT_SECTION + Section: .note.GNU-stack + - Name: .eh_frame + Type: STT_SECTION + Section: .eh_frame + Global: + - Name: bar + Type: STT_FUNC + Section: .text.bar + Size: 0x0000000000000029 + - Name: foo + Type: STT_FUNC + Section: .text.foo + Size: 0x0000000000000029 + - Name: main + Type: STT_FUNC + Section: .text.main + Size: 0x0000000000000029 + - Name: printf +... diff --git a/lld/test/elf/phdr.test b/lld/test/elf/phdr.test index 71ad6ea4725e..755cb8775508 100644 --- a/lld/test/elf/phdr.test +++ b/lld/test/elf/phdr.test @@ -59,7 +59,7 @@ I386-NEXT: Alignment: 4096 I386-NEXT: } I386-NEXT: ProgramHeader { I386-NEXT: Type: PT_LOAD (0x1) -I386-NEXT: Offset: 0x2000 +I386-NEXT: Offset: 0x4000 I386-NEXT: VirtualAddress: 0x4000 I386-NEXT: PhysicalAddress: 0x4000 I386-NEXT: FileSize: 4