[LLD][ELF][AArch64] Add support for SHF_AARCH64_PURECODE ELF section flag (3/3) by Il-Capitano · Pull Request #125689 · llvm/llvm-project (original) (raw)

@llvm/pr-subscribers-llvm-binary-utilities
@llvm/pr-subscribers-backend-aarch64
@llvm/pr-subscribers-lld-elf
@llvm/pr-subscribers-objectyaml
@llvm/pr-subscribers-mc

@llvm/pr-subscribers-lld

Author: Csanád Hajdú (Il-Capitano)

Changes

Add support for the new SHF_AARCH64_PURECODE ELF section flag: ARM-software/abi-aa#304

The general implementation follows the existing one for ARM targets. The output section only has the SHF_AARCH64_PURECODE flag set if all input sections have it set.

Depends on #125687. The changes in that PR are included here as well for now, but will be removed once that gets merged.


Patch is 25.54 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/125689.diff

23 Files Affected:

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index c2aadb2cef5200f..ecfb492522227bc 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -229,6 +229,7 @@ struct Config { StringRef zCetReport = "none"; StringRef zPauthReport = "none"; StringRef zGcsReport = "none";

@@ -1557,10 +1559,12 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) { ErrAlways(ctx) << errPrefix << pat.takeError() << ": " << kv.first; }

@@ -2844,6 +2848,40 @@ static void readSecurityNotes(Ctx &ctx) { ctx.arg.andFeatures &= ~GNU_PROPERTY_AARCH64_FEATURE_1_GCS; }

+static void checkExecuteOnly(Ctx &ctx) {

diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index a2da5543d58670f..c8dc0e5fe033528 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -42,7 +42,8 @@ using namespace lld::elf;

uint32_t OutputSection::getPhdrFlags() const { uint32_t ret = 0;

uint64_t orMask = ~andMask; uint64_t andFlags = (flags & isec->flags) & andMask; uint64_t orFlags = (flags | isec->flags) & orMask; diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index a10af9565a1d631..671a5ec4deccba3 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -1411,6 +1411,7 @@ static std::optional parseFlag(StringRef tok) { .Case(CASE_ENT(SHF_COMPRESSED)) .Case(CASE_ENT(SHF_EXCLUDE)) .Case(CASE_ENT(SHF_ARM_PURECODE))

#undef CASE_ENT } diff --git a/lld/test/ELF/aarch64-execute-only.s b/lld/test/ELF/aarch64-execute-only.s new file mode 100644 index 000000000000000..e67bbf05ff2e215 --- /dev/null +++ b/lld/test/ELF/aarch64-execute-only.s @@ -0,0 +1,33 @@ +// REQUIRES: aarch64 + +// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o +// RUN: ld.lld %t.o -o %t.so -shared +// RUN: llvm-readelf -l %t.so | FileCheck --implicit-check-not=LOAD %s + +// RUN: echo ".section .foo,"ax";
+// RUN: ret" > %t.s +// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %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 --implicit-check-not=LOAD %s + +// CHECK: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000245 0x000245 R 0x10000 +// CHECK: LOAD 0x000248 0x0000000000010248 0x0000000000010248 0x{{.}} 0x{{.}} R E 0x10000 +// CHECK: LOAD 0x00024c 0x000000000002024c 0x000000000002024c 0x{{.}} 0x{{.}} E 0x10000 +// CHECK: LOAD 0x000250 0x0000000000030250 0x0000000000030250 0x000070 0x000db0 RW 0x10000 + +// CHECK: 01 .dynsym .gnu.hash .hash .dynstr +// CHECK: 02 .text +// CHECK: 03 .foo +// CHECK: 04 .dynamic + +// DIFF: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x00020d 0x00020d R 0x10000 +// DIFF: LOAD 0x000210 0x0000000000010210 0x0000000000010210 0x00000c 0x00000c R E 0x10000 +// DIFF: LOAD 0x000220 0x0000000000020220 0x0000000000020220 0x000070 0x000de0 RW 0x10000 + +// DIFF: 01 .dynsym .gnu.hash .hash .dynstr +// DIFF: 02 .text .foo +// DIFF: 03 .dynamic +

diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 8853c4a88b0b593..a5979d029a9eafd 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1300,7 +1300,10 @@ enum : unsigned { SHF_MIPS_STRING = 0x80000000,

// Make code section unreadable when in execute-only mode

// Section Group Flags diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 3c2c7c8c9fed69a..6cfebca9a4d576e 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -547,7 +547,7 @@ static unsigned getELFSectionType(StringRef Name, SectionKind K) { return ELF::SHT_PROGBITS; }

-static unsigned getELFSectionFlags(SectionKind K) { +static unsigned getELFSectionFlags(SectionKind K, const Triple &T) { unsigned Flags = 0;

if (!K.isMetadata() && !K.isExclude()) @@ -559,9 +559,12 @@ static unsigned getELFSectionFlags(SectionKind K) { if (K.isText()) Flags |= ELF::SHF_EXECINSTR;

@@ -840,7 +843,7 @@ static MCSection *selectExplicitSectionGlobal(const GlobalObject *GO, // Infer section flags from the section name if we can. Kind = getELFKindForNamedSection(SectionName, Kind);

@@ -947,7 +950,7 @@ static MCSection *selectELFSectionForGlobal(

MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal( const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {

@@ -967,7 +970,7 @@ MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal( MCSection *TargetLoweringObjectFileELF::getUniqueSectionForFunction( const Function &F, const TargetMachine &TM) const { SectionKind Kind = SectionKind::getText();

diff --git a/llvm/lib/MC/MCSectionELF.cpp b/llvm/lib/MC/MCSectionELF.cpp index 25e62b70b5e2a0c..72a959b1c920825 100644 --- a/llvm/lib/MC/MCSectionELF.cpp +++ b/llvm/lib/MC/MCSectionELF.cpp @@ -118,6 +118,9 @@ void MCSectionELF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T, } else if (T.isARM() || T.isThumb()) { if (Flags & ELF::SHF_ARM_PURECODE) OS << 'y';

diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 539834fc8d4dbfe..05e4d85b2ea5d24 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -803,6 +803,9 @@ void ScalarBitSetTraitsELFYAML::ELF_SHF::bitset(IO &IO, break; } switch (Object->getMachine()) {

case ELF::EM_ARM: BCase(SHF_ARM_PURECODE); break; diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td index 20db70ee38572f2..7c95ba662938d9f 100644 --- a/llvm/lib/Target/AArch64/AArch64Features.td +++ b/llvm/lib/Target/AArch64/AArch64Features.td @@ -635,6 +635,11 @@ def FeatureStrictAlign : SubtargetFeature<"strict-align", "Disallow all unaligned memory " "access">;

+def FeatureExecuteOnly : SubtargetFeature<"execute-only",

diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp index 8729fd4b802c8eb..434ae32502d484b 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp @@ -148,3 +148,29 @@ MCSymbol *AArch64_MachoTargetObjectFile::getAuthPtrSlotSymbol( return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, MachOMMI, RawSym, Key, Discriminator); } + +static bool isExecuteOnlyFunction(const GlobalObject *GO, SectionKind Kind,

};

/// AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin. diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp index a6edcf125782b2c..284278e34f8b4d0 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -262,6 +262,10 @@ bool AArch64TTIImpl::isMultiversionedFunction(const Function &F) const { return F.hasFnAttribute("fmv-features"); }

+const FeatureBitset AArch64TTIImpl::InlineInverseFeatures = {

+}; + bool AArch64TTIImpl::areInlineCompatible(const Function *Caller, const Function *Callee) const { SMEAttrs CallerAttrs(*Caller), CalleeAttrs(*Callee); @@ -284,7 +288,18 @@ bool AArch64TTIImpl::areInlineCompatible(const Function *Caller, return false; }

bool AArch64TTIImpl::areTypesABICompatible( diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h index b65e3c7a1ab20e5..481cb5511a331b7 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h @@ -48,6 +48,8 @@ class AArch64TTIImpl : public BasicTTIImplBase { const AArch64Subtarget *ST; const AArch64TargetLowering *TLI;

diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp index 6b5c5f36cbd4b27..d29d383bc231277 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp @@ -27,6 +27,7 @@ #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -504,6 +505,23 @@ void AArch64TargetELFStreamer::finish() { } }

diff --git a/llvm/test/CodeGen/AArch64/execute-only-section.ll b/llvm/test/CodeGen/AArch64/execute-only-section.ll new file mode 100644 index 000000000000000..15a270b07975e69 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/execute-only-section.ll @@ -0,0 +1,21 @@ +; RUN: llc -mtriple=aarch64 -mattr=+execute-only %s -o - | FileCheck %s + +; CHECK: .section .text,"axy",@progbits,unique,0 +; CHECK-NOT: .section +; CHECK-NOT: .text +; CHECK: .globl test_SectionForGlobal +; CHECK: .type test_SectionForGlobal,@function +define void @test_SectionForGlobal() { +entry: