Index: test/tools/llvm-objcopy/marker-segment.test =================================================================== --- test/tools/llvm-objcopy/marker-segment.test +++ test/tools/llvm-objcopy/marker-segment.test @@ -0,0 +1,86 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-objcopy %t %t2 +# RUN: llvm-readobj -program-headers %t2 | FileCheck %s + +!ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_ARM +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1000 + AddressAlign: 0x0000000000001000 + Content: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x2000 + AddressAlign: 0x0000000000001000 + Content: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + VAddr: 0x1000 + PAddr: 0x1000 + Align: 0x1000 + Sections: + - Section: .text + - Type: PT_LOAD + Flags: [ PF_R, PF_W ] + VAddr: 0x2000 + PAddr: 0x2000 + Align: 0x1000 + Sections: + - Section: .data + - Type: 0x6474e551 # GNU_STACK + Flags: [ PF_R, PF_W ] + VAddr: 0x0000 + PAddr: 0x0000 + Align: 0x0000 + + +#CHECK: ProgramHeaders [ +#CHECK-NEXT: ProgramHeader { +#CHECK-NEXT: Type: PT_LOAD +#CHECK-NEXT: Offset: 0x1000 +#CHECK-NEXT: VirtualAddress: 0x1000 +#CHECK-NEXT: PhysicalAddress: 0x1000 +#CHECK-NEXT: FileSize: 16 +#CHECK-NEXT: MemSize: 16 +#CHECK-NEXT: Flags [ +#CHECK-NEXT: PF_R +#CHECK-NEXT: PF_X +#CHECK-NEXT: ] +#CHECK-NEXT: Alignment: 4096 +#CHECK-NEXT: } +#CHECK-NEXT: ProgramHeader { +#CHECK-NEXT: Type: PT_LOAD +#CHECK-NEXT: Offset: 0x2000 +#CHECK-NEXT: VirtualAddress: 0x2000 +#CHECK-NEXT: PhysicalAddress: 0x2000 +#CHECK-NEXT: FileSize: 16 +#CHECK-NEXT: MemSize: 16 +#CHECK-NEXT: Flags [ +#CHECK-NEXT: PF_R +#CHECK-NEXT: PF_W +#CHECK-NEXT: ] +#CHECK-NEXT: Alignment: 4096 +#CHECK-NEXT: } +#CHECK-NEXT: ProgramHeader { +#CHECK-NEXT: Type: PT_GNU_STACK +#CHECK-NEXT: Offset: 0x0 +#CHECK-NEXT: VirtualAddress: 0x0 +#CHECK-NEXT: PhysicalAddress: 0x0 +#CHECK-NEXT: FileSize: 0 +#CHECK-NEXT: MemSize: 0 +#CHECK-NEXT: Flags [ +#CHECK-NEXT: PF_R +#CHECK-NEXT: PF_W +#CHECK-NEXT: ] +#CHECK-NEXT: Alignment: 0 +#CHECK-NEXT: } +#CHECK-NEXT:] Index: tools/llvm-objcopy/Object.cpp =================================================================== --- tools/llvm-objcopy/Object.cpp +++ tools/llvm-objcopy/Object.cpp @@ -911,8 +911,20 @@ // so that we know that anytime ->ParentSegment is set that segment has // already had its offset properly set. std::vector OrderedSegments; - for (auto &Segment : Obj.segments()) - OrderedSegments.push_back(&Segment); + for (auto &Segment : Obj.segments()) { + // There could exist so-called marker segments, which are only meant + // to signal support of a feature or similar (e.g. GNU_STACK). + // These segments do not have any sections, and have 0 FileSize. + // Other than that their Offset, VAddr, PAddr, and MemSize are also 0. + // Including such a segment in OrderedSegments will produce the lowest + // offset of 0, and will let the following segments overwrite the ELF + // header. + // Here we just check against FileSize as most sensible, since non-zero + // MemSize is technically valid, and non-zero Offset should probably + // not affect any other segments if FileSize is 0 too. + if (Segment.FileSize > 0) + OrderedSegments.push_back(&Segment); + } OrderSegments(OrderedSegments); // The size of ELF + program headers will not change so it is ok to assume // that the first offset of the first segment is a good place to start