--- /dev/null
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy %t %t2
+# RUN: llvm-readobj -program-headers %t2 | FileCheck %s
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1000
+ AddressAlign: 0x1000
+ Size: 0x1000
+ - Name: .text2
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x2000
+ AddressAlign: 0x1000
+ Size: 0x1000
+ - Name: .text3
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x3000
+ AddressAlign: 0x1000
+ Size: 0x1000
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_R ]
+ VAddr: 0x1000
+ PAddr: 0x1000
+ Sections:
+ - Section: .text
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_R ]
+ VAddr: 0x3000
+ PAddr: 0x3000
+ Sections:
+ - Section: .text3
+
+# CHECK: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: VirtualAddress: 0x1000
+# CHECK-NEXT: PhysicalAddress: 0x1000
+# CHECK-NEXT: FileSize: 4096
+# CHECK-NEXT: MemSize: 4096
+# CHECK-NEXT: Flags [ (0x4)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x2000
+# CHECK-NEXT: VirtualAddress: 0x3000
+# CHECK-NEXT: PhysicalAddress: 0x3000
+# CHECK-NEXT: FileSize: 4096
+# CHECK-NEXT: MemSize: 4096
+# CHECK-NEXT: Flags [ (0x5)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: PF_X (0x1)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+# CHECK-NEXT:]
Phdr.p_align = Align;
}
-void Segment::finalize() {
- auto FirstSec = firstSection();
- if (FirstSec) {
- // It is possible for a gap to be at the begining of a segment. Because of
- // this we need to compute the new offset based on how large this gap was
- // in the source file. Section layout should have already ensured that this
- // space is not used for something else.
- uint64_t OriginalOffset = Offset;
- Offset = FirstSec->Offset - (FirstSec->OriginalOffset - OriginalOffset);
- }
-}
-
void Segment::writeSegment(FileOutputBuffer &Out) const {
uint8_t *Buf = Out.getBufferStart() + Offset;
// We want to maintain segments' interstitial data and contents exactly.
} else {
Offset = alignTo(Offset, Segment->Align == 0 ? 1 : Segment->Align);
Segment->Offset = Offset;
- Offset += Segment->FileSize;
}
+ Offset = std::max(Offset, Segment->Offset + Segment->FileSize);
}
// Now the offset of every segment has been set we can assign the offsets
// of each section. For sections that are covered by a segment we should use
Section->Offset =
Segment->Offset + (Section->OriginalOffset - Segment->OriginalOffset);
} else {
- Offset = alignTo(Offset, Section->Offset);
+ Offset = alignTo(Offset, Section->Align == 0 ? 1 : Section->Align);
Section->Offset = Offset;
if (Section->Type != SHT_NOBITS)
Offset += Section->Size;
Section->NameIndex = this->SectionNames->findIndex(Section->Name);
Section->finalize();
}
-
- for (auto &Segment : this->Segments)
- Segment->finalize();
}
template <class ELFT> size_t BinaryObject<ELFT>::totalSize() const {
}
template <class ELFT> void BinaryObject<ELFT>::finalize() {
- for (auto &Segment : this->Segments)
- Segment->finalize();
// Put all segments in offset order.
auto CompareSegments = [](const SegPtr &A, const SegPtr &B) {