summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/test/tools/llvm-objcopy/segment-shift.test70
-rw-r--r--llvm/tools/llvm-objcopy/Object.cpp21
-rw-r--r--llvm/tools/llvm-objcopy/Object.h1
3 files changed, 72 insertions, 20 deletions
diff --git a/llvm/test/tools/llvm-objcopy/segment-shift.test b/llvm/test/tools/llvm-objcopy/segment-shift.test
new file mode 100644
index 00000000000..635fdccf75e
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/segment-shift.test
@@ -0,0 +1,70 @@
+# 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:]
diff --git a/llvm/tools/llvm-objcopy/Object.cpp b/llvm/tools/llvm-objcopy/Object.cpp
index 103937eaac9..3e6606f7095 100644
--- a/llvm/tools/llvm-objcopy/Object.cpp
+++ b/llvm/tools/llvm-objcopy/Object.cpp
@@ -30,18 +30,6 @@ template <class ELFT> void Segment::writeHeader(FileOutputBuffer &Out) const {
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.
@@ -656,8 +644,8 @@ template <class ELFT> void ELFObject<ELFT>::assignOffsets() {
} 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
@@ -673,7 +661,7 @@ template <class ELFT> void ELFObject<ELFT>::assignOffsets() {
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;
@@ -720,9 +708,6 @@ template <class ELFT> void ELFObject<ELFT>::finalize() {
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 {
@@ -742,8 +727,6 @@ void BinaryObject<ELFT>::write(FileOutputBuffer &Out) 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) {
diff --git a/llvm/tools/llvm-objcopy/Object.h b/llvm/tools/llvm-objcopy/Object.h
index 02aeeca7706..398eed7e16c 100644
--- a/llvm/tools/llvm-objcopy/Object.h
+++ b/llvm/tools/llvm-objcopy/Object.h
@@ -93,7 +93,6 @@ public:
Segment *ParentSegment = nullptr;
Segment(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {}
- void finalize();
const SectionBase *firstSection() const {
if (!Sections.empty())
return *Sections.begin();
OpenPOWER on IntegriCloud