Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -681,12 +681,13 @@ RF_NOT_INTERP = 1 << 17, RF_NOT_ALLOC = 1 << 16, RF_WRITE = 1 << 15, - RF_EXEC_WRITE = 1 << 13, - RF_EXEC = 1 << 12, - RF_NON_TLS_BSS = 1 << 11, - RF_NON_TLS_BSS_RO = 1 << 10, - RF_NOT_TLS = 1 << 9, - RF_BSS = 1 << 8, + RF_EXEC_WRITE = 1 << 14, + RF_EXEC = 1 << 13, + RF_NON_TLS_BSS = 1 << 12, + RF_NON_TLS_BSS_RO = 1 << 11, + RF_NOT_TLS = 1 << 10, + RF_BSS = 1 << 9, + RF_PROGBITS = 1 << 8, RF_NOTE = 1 << 7, RF_PPC_NOT_TOCBSS = 1 << 6, RF_PPC_OPD = 1 << 5, @@ -697,7 +698,8 @@ RF_MIPS_NOT_GOT = 1 << 0 }; -static unsigned getSectionRank(const OutputSection *Sec) { +static unsigned getSectionRank(const OutputSection *Sec, + const bool GroupProgBitsSections) { unsigned Rank = 0; // We want to put section specified by -T option first, so we @@ -717,6 +719,13 @@ if (!(Sec->Flags & SHF_ALLOC)) return Rank | RF_NOT_ALLOC; + // Place sections with PROGBITS closer. We want to put progbits + // sections closer as an effort to prevent relocation overflow + // between these sections. We do this only for huge binaries. + bool IsRelRo = isRelroSection(Sec); + if (GroupProgBitsSections && Sec->Type == SHT_PROGBITS && !IsRelRo) + Rank |= RF_PROGBITS; + // Sort sections based on their access permission in the following // order: R, RX, RWX, RW. This order is based on the following // considerations: @@ -757,7 +766,6 @@ // We place nobits RelRo sections before plain r/w ones, and non-nobits RelRo // sections after r/w ones, so that the RelRo sections are contiguous. - bool IsRelRo = isRelroSection(Sec); if (IsNonTlsNoBits && !IsRelRo) Rank |= RF_NON_TLS_BSS_RO; if (!IsNonTlsNoBits && IsRelRo) @@ -1209,11 +1217,19 @@ sortInputSections(); + uint64_t ProgBitsSize = 0; + std::for_each(InputSections.begin(), InputSections.end(), + [&ProgBitsSize](InputSectionBase* SB) { + if (SB->Type == SHT_PROGBITS) + ProgBitsSize += SB->getSize(); + }); + bool GroupProgBitsSections = ProgBitsSize >= (1 << 30); + for (BaseCommand *Base : Script->SectionCommands) { auto *OS = dyn_cast(Base); if (!OS) continue; - OS->SortRank = getSectionRank(OS); + OS->SortRank = getSectionRank(OS, GroupProgBitsSections); // We want to assign rude approximation values to OutSecOff fields // to know the relative order of the input sections. We use it for @@ -1678,17 +1694,20 @@ // The linker is expected to define SECNAME_start and SECNAME_end // symbols for a few sections. This function defines them. template void Writer::addStartEndSymbols() { - auto Define = [&](StringRef Start, StringRef End, OutputSection *OS) { - // These symbols resolve to the image base if the section does not exist. - // A special value -1 indicates end of the section. + // These symbols resolve to the image base or ".text" if the section + // does not exist. Set symbol value to ".text" mitigates the possibilities + // that an relocation from .text section to these symbols overflows. + // A special value -1 indicates end of the section. + OutputSection *DefaultOutSec = findSection(".text"); + if (!DefaultOutSec && Config->Pic) + DefaultOutSec = Out::ElfHeader; + auto Define = [=](StringRef Start, StringRef End, OutputSection *OS) { if (OS) { addOptionalRegular(Start, OS, 0); addOptionalRegular(End, OS, -1); } else { - if (Config->Pic) - OS = Out::ElfHeader; - addOptionalRegular(Start, OS, 0); - addOptionalRegular(End, OS, 0); + addOptionalRegular(Start, DefaultOutSec, 0); + addOptionalRegular(End, DefaultOutSec, 0); } }; Index: test/ELF/pre_init_fini_array_missing.s =================================================================== --- test/ELF/pre_init_fini_array_missing.s +++ test/ELF/pre_init_fini_array_missing.s @@ -14,30 +14,27 @@ call __fini_array_start call __fini_array_end -// With no .init_array section the symbols resolve to 0 -// 0 - (0x201000 + 5) = -2101253 -// 0 - (0x201005 + 5) = -2101258 -// 0 - (0x20100a + 5) = -2101263 -// 0 - (0x20100f + 5) = -2101268 -// 0 - (0x201014 + 5) = -2101273 -// 0 - (0x201019 + 5) = -2101278 +// With no .init_array section the symbols resolve to ".text". // CHECK: Disassembly of section .text: // CHECK-NEXT: _start: -// CHECK-NEXT: 201000: e8 fb ef df ff callq -2101253 -// CHECK-NEXT: 201005: e8 f6 ef df ff callq -2101258 -// CHECK-NEXT: 20100a: e8 f1 ef df ff callq -2101263 -// CHECK-NEXT: 20100f: e8 ec ef df ff callq -2101268 -// CHECK-NEXT: 201014: e8 e7 ef df ff callq -2101273 -// CHECK-NEXT: 201019: e8 e2 ef df ff callq -2101278 +// CHECK-NEXT: 201000: e8 fb ff ff ff callq -5 +// CHECK-NEXT: 201005: e8 f6 ff ff ff callq -10 +// CHECK-NEXT: 20100a: e8 f1 ff ff ff callq -15 +// CHECK-NEXT: 20100f: e8 ec ff ff ff callq -20 +// CHECK-NEXT: 201014: e8 e7 ff ff ff callq -25 +// CHECK-NEXT: 201019: e8 e2 ff ff ff callq -30 -// In position-independent binaries, they resolve to the image base. +// In position-independent binaries, they resolve to ".text". (As +// long as there is no .init_array section, the address of +// __init_array_start / end pair (and alike) does not matter, provided +// that each such pair has same address value.) // PIE: Disassembly of section .text: // PIE-NEXT: _start: -// PIE-NEXT: 1000: e8 fb ef ff ff callq -4101 -// PIE-NEXT: 1005: e8 f6 ef ff ff callq -4106 -// PIE-NEXT: 100a: e8 f1 ef ff ff callq -4111 -// PIE-NEXT: 100f: e8 ec ef ff ff callq -4116 -// PIE-NEXT: 1014: e8 e7 ef ff ff callq -4121 -// PIE-NEXT: 1019: e8 e2 ef ff ff callq -4126 +// PIE-NEXT: 1000: e8 fb ff ff ff callq -5 +// PIE-NEXT: 1005: e8 f6 ff ff ff callq -10 +// PIE-NEXT: 100a: e8 f1 ff ff ff callq -15 +// PIE-NEXT: 100f: e8 ec ff ff ff callq -20 +// PIE-NEXT: 1014: e8 e7 ff ff ff callq -25 +// PIE-NEXT: 1019: e8 e2 ff ff ff callq -30