Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -133,6 +133,7 @@ bool EhFrameHdr; bool EmitRelocs; bool EnableNewDtags; + bool ExecuteOnly; bool ExportDynamic; bool FixCortexA53Errata843419; bool GcSections; Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -302,6 +302,14 @@ if (Config->Pie) error("-r and -pie may not be used together"); } + + if (Config->ExecuteOnly) { + if (Config->EMachine != EM_AARCH64) + error("-execute-only is only supported on AArch64 targets"); + + if (Config->SingleRoRx && !Script->HasSectionsCommand) + error("-execute-only and -no-rosegment cannot be used together"); + } } static const char *getReproduceOption(opt::InputArgList &Args) { @@ -747,6 +755,8 @@ Config->EnableNewDtags = Args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true); Config->Entry = Args.getLastArgValue(OPT_entry); + Config->ExecuteOnly = + Args.hasFlag(OPT_execute_only, OPT_no_execute_only, false); Config->ExportDynamic = Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); Config->FilterList = args::getStrings(Args, OPT_filter); Index: lld/trunk/ELF/Options.td =================================================================== --- lld/trunk/ELF/Options.td +++ lld/trunk/ELF/Options.td @@ -131,6 +131,10 @@ defm exclude_libs: Eq<"exclude-libs", "Exclude static libraries from automatic export">; +defm execute_only: B<"execute-only", + "Do not mark executable sections readable", + "Mark executable sections readable (default)">; + defm export_dynamic: B<"export-dynamic", "Put symbols in the dynamic symbol table", "Do not put symbols in the dynamic symbol table (default)">; Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -1608,6 +1608,15 @@ if (auto *Sec = dyn_cast(Base)) OutputSections.push_back(Sec); + // Ensure data sections are not mixed with executable sections when + // -execute-only is used. + if (Config->ExecuteOnly) + for (OutputSection *OS : OutputSections) + if (OS->Flags & SHF_EXECINSTR) + for (InputSection *IS : getInputSections(OS)) + if (!(IS->Flags & SHF_EXECINSTR)) + error("-execute-only does not support intermingling data and code"); + // Prefer command line supplied address over other constraints. for (OutputSection *Sec : OutputSections) { auto I = Config->SectionStartMap.find(Sec->Name); @@ -1767,6 +1776,8 @@ static uint64_t computeFlags(uint64_t Flags) { if (Config->Omagic) return PF_R | PF_W | PF_X; + if (Config->ExecuteOnly && (Flags & PF_X)) + return Flags & ~PF_R; if (Config->SingleRoRx && !(Flags & PF_W)) return Flags | PF_X; return Flags; Index: lld/trunk/test/ELF/execute-only-mixed-data.s =================================================================== --- lld/trunk/test/ELF/execute-only-mixed-data.s +++ lld/trunk/test/ELF/execute-only-mixed-data.s @@ -0,0 +1,26 @@ +// REQUIRES: aarch64 + +// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o + +// RUN: echo "SECTIONS \ +// RUN: { \ +// RUN: .text : { *(.text) *(.rodata.foo) } \ +// RUN: .rodata : { *(.rodata.bar) } \ +// RUN: }" > %t.lds +// RUN: not ld.lld -T%t.lds %t.o -o %t -execute-only 2>&1 | FileCheck %s + +// RUN: echo "SECTIONS \ +// RUN: { \ +// RUN: .text : { *(.text) } \ +// RUN: .rodata : { *(.rodata.bar) *(.rodata.foo) } \ +// RUN: }" > %t.lds +// RUN: ld.lld -T%t.lds %t.o -o %t -execute-only 2>&1 + +// CHECK: -execute-only does not support intermingling data and code + + br lr + +.section .rodata.foo +.word 0x1 +.section .rodata.bar +.word 0x2 Index: lld/trunk/test/ELF/execute-only.s =================================================================== --- lld/trunk/test/ELF/execute-only.s +++ lld/trunk/test/ELF/execute-only.s @@ -0,0 +1,10 @@ +// REQUIRES: aarch64 + +// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o +// RUN: ld.lld -Ttext=0xcafe0000 %t.o -o %t.so -shared -execute-only +// RUN: llvm-readelf -l %t.so | FileCheck %s + +// CHECK: LOAD {{.*}} 0x00000000cafe0000 0x000004 0x000004 E 0x{{.*}} +// CHECK-NOT: LOAD {{.*}} 0x00000000cafe0000 0x000004 0x000004 R E 0x{{.*}} + + br lr