Index: lib/MC/ELFObjectWriter.cpp =================================================================== --- lib/MC/ELFObjectWriter.cpp +++ lib/MC/ELFObjectWriter.cpp @@ -29,6 +29,7 @@ #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCFragment.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionELF.h" @@ -1066,6 +1067,8 @@ SectionOffsetsTy SectionOffsets; std::vector Groups; std::vector Relocations; + MCSectionELF *TextSection = + static_cast(Ctx.getObjectFileInfo()->getTextSection()); for (MCSection &Sec : Asm) { MCSectionELF &Section = static_cast(Sec); if (Mode == NonDwoOnly && isDwoSection(Section)) @@ -1107,6 +1110,17 @@ SectionIndexMap[RelSection] = addToSectionTable(RelSection); Relocations.push_back(RelSection); } + + // The mix of execute-only and non-execute-only at link time is + // non-execute-only. To avoid the empty implicitly created inaccessible + // .text section from making the whole .text section non-execute-only, we + // mark it execute-only if it is empty and there is at least one + // execute-only section in the object. + if (!TextSection->hasInstructions() && Section.getKind().isExecuteOnly()) { + if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_ARM) { + TextSection->setFlags(TextSection->getFlags() | ELF::SHF_ARM_PURECODE); + } + } } MCSectionELF *CGProfileSection = nullptr; Index: lib/Target/ARM/ARMTargetObjectFile.cpp =================================================================== --- lib/Target/ARM/ARMTargetObjectFile.cpp +++ lib/Target/ARM/ARMTargetObjectFile.cpp @@ -32,7 +32,8 @@ const TargetMachine &TM) { const ARMBaseTargetMachine &ARM_TM = static_cast(TM); bool isAAPCS_ABI = ARM_TM.TargetABI == ARMBaseTargetMachine::ARMABI::ARM_ABI_AAPCS; - // genExecuteOnly = ARM_TM.getSubtargetImpl()->genExecuteOnly(); + bool genExecuteOnly = + ARM_TM.getMCSubtargetInfo()->hasFeature(ARM::FeatureExecuteOnly); TargetLoweringObjectFileELF::Initialize(Ctx, TM); InitializeELF(isAAPCS_ABI); @@ -40,6 +41,17 @@ if (isAAPCS_ABI) { LSDASection = nullptr; } + + // Make code section unreadable when in execute-only mode + if (genExecuteOnly) { + unsigned Type = ELF::SHT_PROGBITS; + unsigned Flags = + ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_ARM_PURECODE; + // Since we cannot modify flags for an existing section, we create a new + // section with the right flags, and use 0 as the unique ID for + // execute-only text + TextSection = Ctx.getELFSection(".text", Type, Flags, 0, "", 0U); + } } const MCExpr *ARMElfTargetObjectFile::getTTypeGlobalReference( Index: test/MC/ARM/elf-execute-only-section.ll =================================================================== --- /dev/null +++ test/MC/ARM/elf-execute-only-section.ll @@ -0,0 +1,13 @@ +; RUN: llc < %s -mtriple=thumbv8m.base-eabi -mattr=+execute-only -filetype=obj %s -o - | \ +; RUN: llvm-readelf -s | FileCheck %s +; RUN: llc < %s -mtriple=thumbv8m.main-eabi -mattr=+execute-only -filetype=obj %s -o - | \ +; RUN: llvm-readelf -s | FileCheck %s +; RUN: llc < %s -mtriple=thumbv7m-eabi -mattr=+execute-only -filetype=obj %s -o - | \ +; RUN: llvm-readelf -s | FileCheck %s + +; CHECK-NOT: {{.text[ ]+PROGBITS[ ]+[0-9]+ [0-9]+ [0-9]+ [0-9]+ AX[^p]}} +; CHECK: {{.text[ ]+PROGBITS[ ]+[0-9]+ [0-9]+ [0-9]+ [0-9]+ AXp}} +define void @test_func() { +entry: + ret void +} Index: test/MC/ELF/ARM/execute-only-populated-text-section.s =================================================================== --- /dev/null +++ test/MC/ELF/ARM/execute-only-populated-text-section.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -filetype=obj -triple thumbv7m-arm-linux-gnu %s -o - \ +// RUN: | llvm-readobj -s -t | FileCheck %s + + .text + bx lr + + .section .text.foo,"axy" + bx lr + +// CHECK: Section { +// CHECK: Name: .text +// CHECK-NEXT: Type: SHT_PROGBITS (0x1) +// CHECK-NEXT: Flags [ (0x6) +// CHECK-NEXT: SHF_ALLOC (0x2) +// CHECK-NEXT: SHF_EXECINSTR (0x4) +// CHECK-NEXT: ] +// CHECK: } + +// CHECK: Section { +// CHECK: Name: .text.foo +// CHECK-NEXT: Type: SHT_PROGBITS (0x1) +// CHECK-NEXT: Flags [ (0x20000006) +// CHECK-NEXT: SHF_ALLOC (0x2) +// CHECK-NEXT: SHF_ARM_PURECODE (0x20000000) +// CHECK-NEXT: SHF_EXECINSTR (0x4) +// CHECK-NEXT: ] +// CHECK: } Index: test/MC/ELF/ARM/execute-only-section.s =================================================================== --- test/MC/ELF/ARM/execute-only-section.s +++ test/MC/ELF/ARM/execute-only-section.s @@ -20,8 +20,9 @@ // CHECK: Section { // CHECK: Name: .text (16) // CHECK-NEXT: Type: SHT_PROGBITS (0x1) -// CHECK-NEXT: Flags [ (0x6) +// CHECK-NEXT: Flags [ (0x20000006) // CHECK-NEXT: SHF_ALLOC (0x2) +// CHECK-NEXT: SHF_ARM_PURECODE (0x20000000) // CHECK-NEXT: SHF_EXECINSTR (0x4) // CHECK-NEXT: ] // CHECK: Size: 0