Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -40,6 +40,7 @@ private: void copyLocalSymbols(); + bool shouldOutputSection(InputSectionBase* C); void createSections(); template void scanRelocs(const InputSection &C, @@ -78,6 +79,7 @@ SymbolTable &Symtab; std::vector Phdrs; + uintX_t GnuStackFlags = 0; uintX_t FileSize; uintX_t SectionHeaderOff; }; @@ -457,6 +459,19 @@ Out::Bss->setSize(Off); } +template +bool Writer::shouldOutputSection(InputSectionBase *C) { + StringRef Name = C->getSectionName(); + if (Name == ".note.GNU-stack") { + GnuStackFlags |= C->getSectionHdr()->sh_flags; + // Just a mark that we saw the gnu stack section and need + // to create GNU_STACK header. + GnuStackFlags |= SHF_WRITE; + return false; + } + return true; +} + static StringRef getOutputName(StringRef S) { if (S.startswith(".text.")) return ".text"; @@ -483,6 +498,8 @@ for (InputSectionBase *C : F->getSections()) { if (!C || !C->isLive() || C == &InputSection::Discarded) continue; + if (!shouldOutputSection(C)) + continue; const Elf_Shdr *H = C->getSectionHdr(); uintX_t OutFlags = H->sh_flags & ~SHF_GROUP; // For SHF_MERGE we create different output sections for each sh_entsize. @@ -769,6 +786,12 @@ copyPhdr(PH, Out::Dynamic); } + if (GnuStackFlags) { + Elf_Phdr *PH = &Phdrs[++PhdrIdx]; + PH->p_type = PT_GNU_STACK; + PH->p_flags = toPhdrFlags(GnuStackFlags); + } + // Fix up PT_INTERP as we now know the address of .interp section. if (Interp) { Interp->p_type = PT_INTERP; @@ -806,6 +829,8 @@ } if (Tls) ++I; + if (GnuStackFlags) + ++I; return I; } Index: test/elf2/Inputs/gnustack.s =================================================================== --- test/elf2/Inputs/gnustack.s +++ test/elf2/Inputs/gnustack.s @@ -0,0 +1 @@ +.section .note.GNU-stack,"x",@progbits Index: test/elf2/Inputs/gnustack2.s =================================================================== --- test/elf2/Inputs/gnustack2.s +++ test/elf2/Inputs/gnustack2.s @@ -0,0 +1 @@ +.section .note.GNU-stack,"",@progbits Index: test/elf2/gnustack.s =================================================================== --- test/elf2/gnustack.s +++ test/elf2/gnustack.s @@ -0,0 +1,125 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/gnustack2.s -o %t3 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 +# RUN: ld.lld2 %t1 %t3 -o %t +# RUN: llvm-readobj --program-headers -s %t | FileCheck --check-prefix=CHECK_RW %s +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/gnustack.s -o %t2 +# RUN: ld.lld2 %t1 %t2 %t3 -o %t +# RUN: llvm-readobj --program-headers %t | FileCheck --check-prefix=CHECK_RWX %s +# RUN: ld.lld2 %t1 -o %t +# RUN: llvm-readobj --program-headers %t | FileCheck --check-prefix=CHECK_NOGNUSTACK %s + +# CHECK_RW: Sections [ +# CHECK_RW-NOT: Name: .note.GNU-stack +# CHECK_RW: ProgramHeaders [ +# CHECK_RW: ProgramHeader { +# CHECK_RW: Type: PT_PHDR +# CHECK_RW: Offset: 0x40 +# CHECK_RW: VirtualAddress: 0x10040 +# CHECK_RW: PhysicalAddress: 0x10040 +# CHECK_RW: FileSize: 224 +# CHECK_RW: MemSize: 224 +# CHECK_RW: Flags [ +# CHECK_RW: PF_R +# CHECK_RW: ] +# CHECK_RW: Alignment: 8 +# CHECK_RW: } +# CHECK_RW: ProgramHeader { +# CHECK_RW: Type: PT_LOAD +# CHECK_RW: Offset: 0x0 +# CHECK_RW: VirtualAddress: 0x10000 +# CHECK_RW: PhysicalAddress: 0x10000 +# CHECK_RW: FileSize: 288 +# CHECK_RW: MemSize: 288 +# CHECK_RW: Flags [ +# CHECK_RW: PF_R +# CHECK_RW: ] +# CHECK_RW: Alignment: 4096 +# CHECK_RW: } +# CHECK_RW: ProgramHeader { +# CHECK_RW: Type: PT_LOAD +# CHECK_RW: Offset: 0x1000 +# CHECK_RW: VirtualAddress: 0x11000 +# CHECK_RW: PhysicalAddress: 0x11000 +# CHECK_RW: FileSize: 0 +# CHECK_RW: MemSize: 0 +# CHECK_RW: Flags [ +# CHECK_RW: PF_R +# CHECK_RW: PF_X +# CHECK_RW: ] +# CHECK_RW: Alignment: 4096 +# CHECK_RW: } +# CHECK_RW: ProgramHeader { +# CHECK_RW: Type: PT_GNU_STACK +# CHECK_RW: Offset: 0x0 +# CHECK_RW: VirtualAddress: 0x0 +# CHECK_RW: PhysicalAddress: 0x0 +# CHECK_RW: FileSize: 0 +# CHECK_RW: MemSize: 0 +# CHECK_RW: Flags [ +# CHECK_RW: PF_R +# CHECK_RW: PF_W +# CHECK_RW: ] +# CHECK_RW: Alignment: 0 +# CHECK_RW: } +# CHECK_RW: ] + +# CHECK_RWX: ProgramHeaders [ +# CHECK_RWX: ProgramHeader { +# CHECK_RWX: Type: PT_PHDR +# CHECK_RWX: Offset: 0x40 +# CHECK_RWX: VirtualAddress: 0x10040 +# CHECK_RWX: PhysicalAddress: 0x10040 +# CHECK_RWX: FileSize: 224 +# CHECK_RWX: MemSize: 224 +# CHECK_RWX: Flags [ +# CHECK_RWX: PF_R +# CHECK_RWX: ] +# CHECK_RWX: Alignment: 8 +# CHECK_RWX: } +# CHECK_RWX: ProgramHeader { +# CHECK_RWX: Type: PT_LOAD +# CHECK_RWX: Offset: 0x0 +# CHECK_RWX: VirtualAddress: 0x10000 +# CHECK_RWX: PhysicalAddress: 0x10000 +# CHECK_RWX: FileSize: 288 +# CHECK_RWX: MemSize: 288 +# CHECK_RWX: Flags [ +# CHECK_RWX: PF_R +# CHECK_RWX: ] +# CHECK_RWX: Alignment: 4096 +# CHECK_RWX: } +# CHECK_RWX: ProgramHeader { +# CHECK_RWX: Type: PT_LOAD +# CHECK_RWX: Offset: 0x1000 +# CHECK_RWX: VirtualAddress: 0x11000 +# CHECK_RWX: PhysicalAddress: 0x11000 +# CHECK_RWX: FileSize: 0 +# CHECK_RWX: MemSize: 0 +# CHECK_RWX: Flags [ +# CHECK_RWX: PF_R +# CHECK_RWX: PF_X +# CHECK_RWX: ] +# CHECK_RWX: Alignment: 4096 +# CHECK_RWX: } +# CHECK_RWX: ProgramHeader { +# CHECK_RWX: Type: PT_GNU_STACK +# CHECK_RWX: Offset: 0x0 +# CHECK_RWX: VirtualAddress: 0x0 +# CHECK_RWX: PhysicalAddress: 0x0 +# CHECK_RWX: FileSize: 0 +# CHECK_RWX: MemSize: 0 +# CHECK_RWX: Flags [ +# CHECK_RWX: PF_R +# CHECK_RWX: PF_W +# CHECK_RWX: PF_X +# CHECK_RWX: ] +# CHECK_RWX: Alignment: 0 +# CHECK_RWX: } +# CHECK_RWX: ] + +# CHECK_NOGNUSTACK: ProgramHeaders [ +# CHECK_NOGNUSTACK-NOT: Type: PT_GNU_STACK + +.globl _start +_start: