Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -45,7 +45,9 @@ std::vector elf::OutputSections; uint32_t OutputSection::getPhdrFlags() const { - uint32_t Ret = PF_R; + uint32_t Ret = 0; + if (Config->EMachine != EM_ARM || !(Flags & SHF_ARM_PURECODE)) + Ret |= PF_R; if (Flags & SHF_WRITE) Ret |= PF_W; if (Flags & SHF_EXECINSTR) @@ -91,10 +93,11 @@ void OutputSection::addSection(InputSection *IS) { if (!Live) { // If IS is the first section to be added to this section, - // initialize Type and Entsize from IS. + // initialize Type, Entsize and flags from IS. Live = true; Type = IS->Type; Entsize = IS->Entsize; + Flags = IS->Flags; } else { // Otherwise, check if new type or flags are compatible with existing ones. if ((Flags & (SHF_ALLOC | SHF_TLS)) != (IS->Flags & (SHF_ALLOC | SHF_TLS))) @@ -114,7 +117,12 @@ } IS->Parent = this; - Flags |= IS->Flags; + uint64_t AndMask = Config->EMachine == EM_ARM ? SHF_ARM_PURECODE : 0; + uint64_t OrMask = ~AndMask; + uint64_t AndFlags = (Flags & IS->Flags) & AndMask; + uint64_t OrFlags = (Flags | IS->Flags) & OrMask; + Flags = AndFlags | OrFlags; + Alignment = std::max(Alignment, IS->Alignment); IS->OutSecOff = Size++; Index: test/ELF/arm-execute-only.s =================================================================== --- /dev/null +++ test/ELF/arm-execute-only.s @@ -0,0 +1,38 @@ +// RUN: llvm-mc -filetype=obj -triple=armv7-pc-linux %s -o %t.o +// RUN: ld.lld %t.o -o %t.so -shared +// RUN: llvm-readelf -l %t.so | FileCheck %s + +// RUN: ld.lld %t.o %t.o -o %t.so -shared +// RUN: llvm-readelf -l %t.so | FileCheck %s + +// RUN: echo ".section .foo,\"ax\"; \ +// RUN: bx lr" > %t.s +// RUN: llvm-mc -filetype=obj -triple=armv7-pc-linux %t.s -o %t2.o +// RUN: ld.lld %t.o %t2.o -o %t.so -shared +// RUN: llvm-readelf -l %t.so | FileCheck --check-prefix=DIFF %s + +// CHECK-NOT: LOAD +// CHECK: LOAD 0x000000 0x00000000 0x00000000 0x00169 0x00169 R 0x1000 +// CHECK: LOAD 0x001000 0x00001000 0x00001000 0x{{.*}} 0x{{.*}} R E 0x1000 +// CHECK: LOAD 0x002000 0x00002000 0x00002000 0x{{.*}} 0x{{.*}} E 0x1000 +// CHECK: LOAD 0x003000 0x00003000 0x00003000 0x00038 0x00038 RW 0x1000 +// CHECK-NOT: LOAD + +// CHECK: 01 .dynsym .gnu.hash .hash .dynstr +// CHECK: 02 .text +// CHECK: 03 .foo +// CHECK: 04 .dynamic + +// DIFF-NOT: LOAD +// DIFF: LOAD 0x000000 0x00000000 0x00000000 0x00149 0x00149 R 0x1000 +// DIFF: LOAD 0x001000 0x00001000 0x00001000 0x0000c 0x0000c R E 0x1000 +// DIFF: LOAD 0x002000 0x00002000 0x00002000 0x00038 0x00038 RW 0x1000 +// DIFF-NOT: LOAD + +// DIFF: 01 .dynsym .gnu.hash .hash .dynstr +// DIFF: 02 .text .foo +// DIFF: 03 .dynamic + + bx lr + .section .foo,"axy" + bx lr