Skip to content

Commit

Permalink
[AArch64] Support execute-only LOAD segments.
Browse files Browse the repository at this point in the history
Summary:
This adds an LLD flag to mark executable LOAD segments execute-only for AArch64 targets. 

In AArch64 the expectation is that code is execute-only compatible, so this just adds a linker option to enforce this.

Patch by: ivanlozano (Ivan Lozano)

Reviewers: srhines, echristo, peter.smith, eugenis, javed.absar, espindola, ruiu

Reviewed By: ruiu

Subscribers: dokyungs, emaste, arichardson, kristof.beyls, llvm-commits

Differential Revision: https://reviews.llvm.org/D49456

llvm-svn: 338271
  • Loading branch information
davidbolvansky committed Jul 30, 2018
1 parent 2fa7fb1 commit a932cd4
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 0 deletions.
1 change: 1 addition & 0 deletions lld/ELF/Config.h
Expand Up @@ -133,6 +133,7 @@ struct Configuration {
bool EhFrameHdr;
bool EmitRelocs;
bool EnableNewDtags;
bool ExecuteOnly;
bool ExportDynamic;
bool FixCortexA53Errata843419;
bool GcSections;
Expand Down
10 changes: 10 additions & 0 deletions lld/ELF/Driver.cpp
Expand Up @@ -302,6 +302,14 @@ static void checkOptions(opt::InputArgList &Args) {
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) {
Expand Down Expand Up @@ -747,6 +755,8 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
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);
Expand Down
4 changes: 4 additions & 0 deletions lld/ELF/Options.td
Expand Up @@ -131,6 +131,10 @@ def error_unresolved_symbols: F<"error-unresolved-symbols">,

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)">;
Expand Down
11 changes: 11 additions & 0 deletions lld/ELF/Writer.cpp
Expand Up @@ -1608,6 +1608,15 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (auto *Sec = dyn_cast<OutputSection>(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);
Expand Down Expand Up @@ -1767,6 +1776,8 @@ static bool needsPtLoad(OutputSection *Sec) {
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;
Expand Down
26 changes: 26 additions & 0 deletions lld/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
10 changes: 10 additions & 0 deletions lld/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

0 comments on commit a932cd4

Please sign in to comment.