uintX_t FileSize;
uintX_t SectionHeaderOff;
+ bool AllocateHeader = true;
};
} // anonymous namespace
if (Config->Relocatable) {
assignFileOffsets();
} else {
- // Binary output does not have PHDRS.
- if (!Config->OFormatBinary) {
- Phdrs = Script<ELFT>::X->hasPhdrsCommands()
- ? Script<ELFT>::X->createPhdrs()
- : createPhdrs();
- addPtArmExid(Phdrs);
- fixHeaders();
- }
-
if (ScriptConfig->HasSections) {
Script<ELFT>::X->assignAddresses(Phdrs);
} else {
if (!AIsAlloc)
return false;
+ // We want to put section specified by -T option first, so we
+ // can start assigning VA starting from them later.
+ auto AAddrSetI = Config->SectionStartMap.find(A->getName());
+ auto BAddrSetI = Config->SectionStartMap.find(B->getName());
+ bool AHasAddrSet = AAddrSetI != Config->SectionStartMap.end();
+ bool BHasAddrSet = BAddrSetI != Config->SectionStartMap.end();
+ if (AHasAddrSet != BHasAddrSet)
+ return AHasAddrSet;
+ if (AHasAddrSet)
+ return AAddrSetI->second < BAddrSetI->second;
+
// We want the read only sections first so that they go in the PT_LOAD
// covering the program headers at the start of the file.
bool AIsWritable = A->Flags & SHF_WRITE;
Sec->ShName = In<ELFT>::ShStrTab->addString(Sec->getName());
}
+ // Binary and relocatable output does not have PHDRS.
+ // The headers have to be created before finalize as that can influence the
+ // image base and the dynamic section on mips includes the image base.
+ if (!Config->Relocatable && !Config->OFormatBinary) {
+ Phdrs = Script<ELFT>::X->hasPhdrsCommands() ? Script<ELFT>::X->createPhdrs()
+ : createPhdrs();
+ addPtArmExid(Phdrs);
+ fixHeaders();
+ }
+
// Fill other section headers. The dynamic table is finalized
// at the end because some tags like RELSZ depend on result
// of finalizing other sections.
// Add the first PT_LOAD segment for regular output sections.
uintX_t Flags = computeFlags<ELFT>(PF_R);
PhdrEntry *Load = AddHdr(PT_LOAD, Flags);
- if (!ScriptConfig->HasSections) {
- Load->add(Out<ELFT>::ElfHeader);
- Load->add(Out<ELFT>::ProgramHeaders);
- }
PhdrEntry TlsHdr(PT_TLS, PF_R);
PhdrEntry RelRo(PT_GNU_RELRO, PF_R);
// have to be page aligned so that the dynamic linker can set the permissions.
template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
for (const PhdrEntry &P : Phdrs)
- if (P.p_type == PT_LOAD)
+ if (P.p_type == PT_LOAD && P.First)
P.First->PageAlign = true;
for (const PhdrEntry &P : Phdrs) {
}
}
+template <class ELFT>
+void elf::allocateHeaders(MutableArrayRef<PhdrEntry> Phdrs,
+ ArrayRef<OutputSectionBase *> OutputSections) {
+ auto FirstPTLoad =
+ std::find_if(Phdrs.begin(), Phdrs.end(),
+ [](const PhdrEntry &E) { return E.p_type == PT_LOAD; });
+ if (FirstPTLoad == Phdrs.end())
+ return;
+ if (FirstPTLoad->First)
+ for (OutputSectionBase *Sec : OutputSections)
+ if (Sec->FirstInPtLoad == FirstPTLoad->First)
+ Sec->FirstInPtLoad = Out<ELFT>::ElfHeader;
+ FirstPTLoad->First = Out<ELFT>::ElfHeader;
+ if (!FirstPTLoad->Last)
+ FirstPTLoad->Last = Out<ELFT>::ProgramHeaders;
+}
+
// We should set file offsets and VAs for elf header and program headers
// sections. These are special, we do not include them into output sections
// list, but have them to simplify the code.
// If the script has SECTIONS, assignAddresses will compute the values.
if (ScriptConfig->HasSections)
return;
+
+ uintX_t HeaderSize = getHeaderSize<ELFT>();
+ // When -T<section> option is specified, lower the base to make room for those
+ // sections.
+ if (!Config->SectionStartMap.empty()) {
+ uint64_t Min = -1;
+ for (const auto &P : Config->SectionStartMap)
+ Min = std::min(Min, P.second);
+ if (HeaderSize < Min)
+ Min -= HeaderSize;
+ else
+ AllocateHeader = false;
+ if (Min < Config->ImageBase)
+ Config->ImageBase = alignDown(Min, Config->MaxPageSize);
+ }
+
+ if (AllocateHeader)
+ allocateHeaders<ELFT>(Phdrs, OutputSections);
+
uintX_t BaseVA = Config->ImageBase;
Out<ELFT>::ElfHeader->Addr = BaseVA;
Out<ELFT>::ProgramHeaders->Addr = BaseVA + Out<ELFT>::ElfHeader->Size;
// Assign VAs (addresses at run-time) to output sections.
template <class ELFT> void Writer<ELFT>::assignAddresses() {
- uintX_t VA = Config->ImageBase + getHeaderSize<ELFT>();
+ uintX_t VA = Config->ImageBase;
+ if (AllocateHeader)
+ VA += getHeaderSize<ELFT>();
uintX_t ThreadBssOffset = 0;
for (OutputSectionBase *Sec : OutputSections) {
uintX_t Alignment = Sec->Addralign;
template void elf::writeResult<ELF64LE>();
template void elf::writeResult<ELF64BE>();
+template void elf::allocateHeaders<ELF32LE>(MutableArrayRef<PhdrEntry>,
+ ArrayRef<OutputSectionBase *>);
+template void elf::allocateHeaders<ELF32BE>(MutableArrayRef<PhdrEntry>,
+ ArrayRef<OutputSectionBase *>);
+template void elf::allocateHeaders<ELF64LE>(MutableArrayRef<PhdrEntry>,
+ ArrayRef<OutputSectionBase *>);
+template void elf::allocateHeaders<ELF64BE>(MutableArrayRef<PhdrEntry>,
+ ArrayRef<OutputSectionBase *>);
+
template bool elf::isRelroSection<ELF32LE>(const OutputSectionBase *);
template bool elf::isRelroSection<ELF32BE>(const OutputSectionBase *);
template bool elf::isRelroSection<ELF64LE>(const OutputSectionBase *);
--- /dev/null
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+
+## Show what regular output gives to us.
+# RUN: ld.lld %t.o -o %t1
+# RUN: llvm-readobj --elf-output-style=GNU -l -s %t1 | FileCheck %s
+# CHECK: .rodata PROGBITS 0000000000200158 000158 000008
+# CHECK-NEXT: .text PROGBITS 0000000000201000 001000 000001
+# CHECK-NEXT: .aw PROGBITS 0000000000202000 002000 000008
+# CHECK-NEXT: .data PROGBITS 0000000000202008 002008 000008
+# CHECK-NEXT: .bss NOBITS 0000000000202010 002010 000008
+# CHECK: PHDR
+# CHECK-NEXT: LOAD 0x000000 0x0000000000200000
+
+## With .text at 0 there is no space to allocate the headers.
+# RUN: ld.lld -Ttext 0x0 -Tdata 0x4000 -Tbss 0x8000 %t.o -o %t2
+# RUN: llvm-readobj --elf-output-style=GNU -l -s %t2 | FileCheck %s --check-prefix=USER1
+# USER1: .text PROGBITS 0000000000000000 001000 000001
+# USER1-NEXT: .data PROGBITS 0000000000004000 002000 000008
+# USER1-NEXT: .bss NOBITS 0000000000008000 002008 000008
+# USER1-NEXT: .rodata PROGBITS 0000000000009000 003000 000008
+# USER1-NEXT: .aw PROGBITS 000000000000a000 004000 000008
+# USER1: PHDR
+# USER1-NEXT: LOAD 0x001000 0x0000000000000000
+
+## With .text at 0x1000 there is space to allocate the headers.
+# RUN: ld.lld -Ttext 0x1000 -Tdata 0x4000 -Tbss 0x8000 %t.o -o %t3
+# RUN: llvm-readobj --elf-output-style=GNU -l -s %t3 | FileCheck %s --check-prefix=USER2
+# USER2: .text PROGBITS 0000000000001000 001000 000001
+# USER2-NEXT: .data PROGBITS 0000000000004000 002000 000008
+# USER2-NEXT: .bss NOBITS 0000000000008000 002008 000008
+# USER2-NEXT: .rodata PROGBITS 0000000000009000 003000 000008
+# USER2-NEXT: .aw PROGBITS 000000000000a000 004000 000008
+# USER2: PHDR
+# USER2-NEXT: LOAD 0x000000 0x0000000000000000
+
+## With .text well above 200000 we don't need to change the image base
+# RUN: ld.lld -Ttext 0x201000 %t.o -o %t4
+# RUN: llvm-readobj --elf-output-style=GNU -l -s %t4 | FileCheck %s --check-prefix=USER3
+# USER3: .text PROGBITS 0000000000201000 001000 000001
+# USER3-NEX: .rodata PROGBITS 0000000000202000 002000 000008
+# USER3-NEX: .aw PROGBITS 0000000000203000 003000 000008
+# USER3-NEX: .data PROGBITS 0000000000203008 003008 000008
+# USER3-NEX: .bss NOBITS 0000000000203010 003010 000008
+# USER3: PHDR
+# USER3-NEXT: LOAD 0x000000 0x0000000000200000
+
+.text
+.globl _start
+_start:
+ nop
+
+.section .rodata,"a"
+ .quad 0
+
+.section .aw,"aw"
+ .quad 0
+
+.section .data,"aw"
+ .quad 0
+
+.section .bss,"",@nobits
+ .quad 0