=?utf-8?q?Csanád_Hajdú?= <csanad.ha...@arm.com> Message-ID: In-Reply-To: <llvm.org/llvm/llvm-project/pull/125...@github.com>
llvmbot wrote: <!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-llvm-binary-utilities Author: Csanád Hajdú (Il-Capitano) <details> <summary>Changes</summary> Add support for the new SHF_AARCH64_PURECODE ELF section flag: https://github.com/ARM-software/abi-aa/pull/304 The general implementation follows the existing one for ARM targets. Simlarly to ARM targets, generating object files with the `SHF_AARCH64_PURECODE` flag set is enabled by the `-mexecute-only`/`-mpure-code` driver flag. Depends on https://github.com/llvm/llvm-project/pull/125687. The changes in that PR are included here as well for now, but will be removed once that gets merged. --- Patch is 26.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/125688.diff 23 Files Affected: - (modified) clang/include/clang/Driver/Options.td (+2-2) - (modified) clang/lib/Driver/ToolChains/Arch/AArch64.cpp (+11) - (added) clang/test/CodeGen/aarch64-execute-only.c (+24) - (added) clang/test/Driver/aarch64-execute-only.c (+6) - (modified) clang/test/Driver/fsanitize.c (+7-1) - (modified) llvm/include/llvm/BinaryFormat/ELF.h (+4-1) - (modified) llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (+8-5) - (modified) llvm/lib/MC/MCParser/ELFAsmParser.cpp (+5-2) - (modified) llvm/lib/MC/MCSectionELF.cpp (+3) - (modified) llvm/lib/ObjectYAML/ELFYAML.cpp (+3) - (modified) llvm/lib/Target/AArch64/AArch64Features.td (+5) - (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp (+26) - (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.h (+6) - (modified) llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp (+16-1) - (modified) llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h (+2) - (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp (+18) - (added) llvm/test/CodeGen/AArch64/execute-only-section.ll (+21) - (added) llvm/test/MC/ELF/AArch64/execute-only-populated-text-section.s (+27) - (added) llvm/test/MC/ELF/AArch64/execute-only-section.s (+43) - (added) llvm/test/MC/ELF/AArch64/execute-only-text-section-data.s (+27) - (modified) llvm/test/MC/ELF/section-flags-unknown.s (+3) - (modified) llvm/test/Transforms/Inline/AArch64/inline-target-attr.ll (+25) - (modified) llvm/tools/llvm-readobj/ELFDumper.cpp (+8) ``````````diff diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 0ab923fcdd5838c..028d74c9711d1f0 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4677,9 +4677,9 @@ def mno_long_calls : Flag<["-"], "mno-long-calls">, Group<m_Group>, HelpText<"Restore the default behaviour of not generating long calls">; } // let Flags = [TargetSpecific] def mexecute_only : Flag<["-"], "mexecute-only">, Group<m_arm_Features_Group>, - HelpText<"Disallow generation of data access to code sections (ARM only)">; + HelpText<"Disallow generation of data access to code sections (AArch64/ARM only)">; def mno_execute_only : Flag<["-"], "mno-execute-only">, Group<m_arm_Features_Group>, - HelpText<"Allow generation of data access to code sections (ARM only)">; + HelpText<"Allow generation of data access to code sections (AArch64/ARM only)">; let Flags = [TargetSpecific] in { def mtp_mode_EQ : Joined<["-"], "mtp=">, Group<m_arm_Features_Group>, Values<"soft,cp15,tpidrurw,tpidruro,tpidrprw,el0,el1,el2,el3,tpidr_el0,tpidr_el1,tpidr_el2,tpidr_el3,tpidrro_el0">, HelpText<"Thread pointer access method. " diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp index 1e2ac4e501bafd1..1248fea50f9de2b 100644 --- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -332,6 +332,17 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, } else if (Triple.isOSOpenBSD()) Features.push_back("+strict-align"); + // Generate execute-only output (no data access to code sections). + // This only makes sense for the compiler, not for the assembler. + if (!ForAS) { + if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, + options::OPT_mno_execute_only)) { + if (A->getOption().matches(options::OPT_mexecute_only)) { + Features.push_back("+execute-only"); + } + } + } + if (Args.hasArg(options::OPT_ffixed_x1)) Features.push_back("+reserve-x1"); diff --git a/clang/test/CodeGen/aarch64-execute-only.c b/clang/test/CodeGen/aarch64-execute-only.c new file mode 100644 index 000000000000000..d885e954166f674 --- /dev/null +++ b/clang/test/CodeGen/aarch64-execute-only.c @@ -0,0 +1,24 @@ +// RUN: %clang -target aarch64 -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target aarch64 -### -mexecute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target aarch64 -### -mexecute-only -mno-execute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + + +// -mpure-code flag for GCC compatibility +// RUN: %clang -target aarch64 -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target aarch64 -### -mpure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target aarch64 -### -mpure-code -mno-pure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// CHECK-NO-EXECUTE-ONLY-NOT: "+execute-only" +// CHECK-EXECUTE-ONLY: "+execute-only" + +void a() {} diff --git a/clang/test/Driver/aarch64-execute-only.c b/clang/test/Driver/aarch64-execute-only.c new file mode 100644 index 000000000000000..67c6d4a5eb06699 --- /dev/null +++ b/clang/test/Driver/aarch64-execute-only.c @@ -0,0 +1,6 @@ +// RUN: %clang --sysroot=%S/Inputs -c -fdriver-only -Werror --target=aarch64-unknown-linux-gnu \ +// RUN: -mexecute-only %s 2>&1 | count 0 + +// RUN: %clang -### --target=aarch64-unknown-linux-gnu -x assembler -mexecute-only %s -c -### 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NO-EXECUTE-ONLY-ASM +// CHECK-NO-EXECUTE-ONLY-ASM: warning: argument unused during compilation: '-mexecute-only' diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 429dc51b3356d68..cb3b75cbd27a7be 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -1052,7 +1052,6 @@ // RUN: not %clang --target=x86_64-sie-ps5 -fsanitize=kcfi %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-KCFI-TARGET // RUN: not %clang --target=x86_64-sie-ps5 -fsanitize=function -fsanitize=kcfi %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-KCFI-TARGET --check-prefix=CHECK-UBSAN-FUNCTION-TARGET // RUN: %clang --target=x86_64-sie-ps5 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-UNDEFINED -// CHECK-UBSAN-UNDEFINED: "-fsanitize={{((alignment|array-bounds|bool|builtin|enum|float-cast-overflow|integer-divide-by-zero|nonnull-attribute|null|pointer-overflow|return|returns-nonnull-attribute|shift-base|shift-exponent|signed-integer-overflow|unreachable|vla-bound),?){17}"}} // RUN: not %clang --target=armv6t2-eabi -mexecute-only -fsanitize=function %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-FUNCTION-MEXECUTE-ONLY // RUN: not %clang --target=armv6t2-eabi -mpure-code -fsanitize=function %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-FUNCTION-MPURE-CODE @@ -1060,12 +1059,19 @@ // RUN: not %clang --target=armv6t2-eabi -mpure-code -fsanitize=kcfi %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-KCFI-MPURE-CODE // RUN: %clang --target=armv6t2-eabi -mexecute-only -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-UNDEFINED-VPTR +// RUN: not %clang --target=aarch64 -mexecute-only -fsanitize=function %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-FUNCTION-MEXECUTE-ONLY +// RUN: not %clang --target=aarch64 -mpure-code -fsanitize=function %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-FUNCTION-MPURE-CODE +// RUN: not %clang --target=aarch64 -mexecute-only -fsanitize=kcfi %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-KCFI-MEXECUTE-ONLY +// RUN: not %clang --target=aarch64 -mpure-code -fsanitize=kcfi %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-KCFI-MPURE-CODE +// RUN: %clang --target=aarch64 -mexecute-only -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-UNDEFINED + // CHECK-UBSAN-KCFI-TARGET-DAG: error: unsupported option '-fsanitize=kcfi' for target 'x86_64-sie-ps5' // CHECK-UBSAN-KCFI-MEXECUTE-ONLY-DAG: error: invalid argument '-fsanitize=kcfi' not allowed with '-mexecute-only' // CHECK-UBSAN-KCFI-MPURE-CODE-DAG: error: invalid argument '-fsanitize=kcfi' not allowed with '-mpure-code' // CHECK-UBSAN-FUNCTION-TARGET-DAG: error: unsupported option '-fsanitize=function' for target 'x86_64-sie-ps5' // CHECK-UBSAN-FUNCTION-MEXECUTE-ONLY-DAG: error: invalid argument '-fsanitize=function' not allowed with '-mexecute-only' // CHECK-UBSAN-FUNCTION-MPURE-CODE-DAG: error: invalid argument '-fsanitize=function' not allowed with '-mpure-code' +// CHECK-UBSAN-UNDEFINED: "-fsanitize={{((alignment|array-bounds|bool|builtin|enum|float-cast-overflow|integer-divide-by-zero|nonnull-attribute|null|pointer-overflow|return|returns-nonnull-attribute|shift-base|shift-exponent|signed-integer-overflow|unreachable|vla-bound),?){17}"}} // CHECK-UBSAN-UNDEFINED-VPTR: "-fsanitize={{((alignment|array-bounds|bool|builtin|enum|float-cast-overflow|integer-divide-by-zero|nonnull-attribute|null|pointer-overflow|return|returns-nonnull-attribute|shift-base|shift-exponent|signed-integer-overflow|unreachable|vla-bound|vptr),?){18}"}} // * Test BareMetal toolchain sanitizer support * 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 - SHF_ARM_PURECODE = 0x20000000 + SHF_ARM_PURECODE = 0x20000000, + + // Section contains only program instructions and no program data. + SHF_AARCH64_PURECODE = 0x20000000 }; // 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; - if (K.isExecuteOnly()) + if ((T.isARM() || T.isThumb()) && K.isExecuteOnly()) Flags |= ELF::SHF_ARM_PURECODE; + if (T.isAArch64() && K.isExecuteOnly()) + Flags |= ELF::SHF_AARCH64_PURECODE; + if (K.isWriteable()) Flags |= ELF::SHF_WRITE; @@ -840,7 +843,7 @@ static MCSection *selectExplicitSectionGlobal(const GlobalObject *GO, // Infer section flags from the section name if we can. Kind = getELFKindForNamedSection(SectionName, Kind); - unsigned Flags = getELFSectionFlags(Kind); + unsigned Flags = getELFSectionFlags(Kind, TM.getTargetTriple()); auto [Group, IsComdat, ExtraFlags] = getGlobalObjectInfo(GO, TM); Flags |= ExtraFlags; @@ -947,7 +950,7 @@ static MCSection *selectELFSectionForGlobal( MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal( const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { - unsigned Flags = getELFSectionFlags(Kind); + unsigned Flags = getELFSectionFlags(Kind, TM.getTargetTriple()); // If we have -ffunction-section or -fdata-section then we should emit the // global value to a uniqued section specifically for it. @@ -967,7 +970,7 @@ MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal( MCSection *TargetLoweringObjectFileELF::getUniqueSectionForFunction( const Function &F, const TargetMachine &TM) const { SectionKind Kind = SectionKind::getText(); - unsigned Flags = getELFSectionFlags(Kind); + unsigned Flags = getELFSectionFlags(Kind, TM.getTargetTriple()); // If the function's section names is pre-determined via pragma or a // section attribute, call selectExplicitSectionGlobal. if (F.hasSection()) diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp index b58210b3c268e99..99b13c68a9966c7 100644 --- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -328,9 +328,12 @@ static unsigned parseSectionFlags(const Triple &TT, StringRef flagsStr, flags |= ELF::XCORE_SHF_DP_SECTION; break; case 'y': - if (!(TT.isARM() || TT.isThumb())) + if (TT.isARM() || TT.isThumb()) + flags |= ELF::SHF_ARM_PURECODE; + else if (TT.isAArch64()) + flags |= ELF::SHF_AARCH64_PURECODE; + else return -1U; - flags |= ELF::SHF_ARM_PURECODE; break; case 's': if (TT.getArch() != Triple::hexagon) 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'; + } else if (T.isAArch64()) { + if (Flags & ELF::SHF_AARCH64_PURECODE) + OS << 'y'; } else if (Arch == Triple::hexagon) { if (Flags & ELF::SHF_HEX_GPREL) OS << 's'; 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 ScalarBitSetTraits<ELFYAML::ELF_SHF>::bitset(IO &IO, break; } switch (Object->getMachine()) { + case ELF::EM_AARCH64: + BCase(SHF_AARCH64_PURECODE); + break; 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", + "GenExecuteOnly", "true", + "Enable the generation of " + "execute only code.">; + foreach i = {1-7,9-15,18,20-28} in def FeatureReserveX#i : SubtargetFeature<"reserve-x"#i, "ReserveXRegister["#i#"]", "true", "Reserve X"#i#", making it unavailable " 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, + const TargetMachine &TM) { + if (const Function *F = dyn_cast<Function>(GO)) + if (TM.getSubtarget<AArch64Subtarget>(*F).genExecuteOnly() && Kind.isText()) + return true; + return false; +} + +MCSection *AArch64_ELFTargetObjectFile::getExplicitSectionGlobal( + const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { + // Set execute-only access for the explicit section + if (isExecuteOnlyFunction(GO, Kind, TM)) + Kind = SectionKind::getExecuteOnly(); + + return TargetLoweringObjectFileELF::getExplicitSectionGlobal(GO, Kind, TM); +} + +MCSection *AArch64_ELFTargetObjectFile::SelectSectionForGlobal( + const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { + // Set execute-only access for the explicit section + if (isExecuteOnlyFunction(GO, Kind, TM)) + Kind = SectionKind::getExecuteOnly(); + + return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM); +} diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h index 0c822ac84f200c7..3e9cd51b742a29c 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h +++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h @@ -39,6 +39,12 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF { void emitPersonalityValueImpl(MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym, const MachineModuleInfo *MMI) const override; + + MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, + const TargetMachine &TM) const override; + + MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, + const TargetMachine &TM) const override; }; /// 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 = { + AArch64::FeatureExecuteOnly, +}; + 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; } - return BaseT::areInlineCompatible(Caller, Callee); + const TargetMachine &TM = getTLI()->getTargetMachine(); + const FeatureBitset &CallerBits = + TM.getSubtargetImpl(*Caller)->getFeatureBits(); + const FeatureBitset &CalleeBits = + TM.getSubtargetImpl(*Callee)->getFeatureBits(); + // Adjust the feature bitsets by inverting some of the bits. This is needed + // for target features that represent restrictions rather than capabilities, + // for example "+execute-only". + FeatureBitset EffectiveCallerBits = CallerBits ^ InlineInverseFeatures; + FeatureBitset EffectiveCalleeBits = CalleeBits ^ InlineInverseFeatures; + + return (EffectiveCallerBits & EffectiveCalleeBits) == EffectiveCalleeBits; } 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<AArch64TTIImpl> { const AArch64Subtarget *ST; const AArch64TargetLowering *TLI; + static const FeatureBitset InlineInverseFeatures; + const AArch64Subtarget *getST() const { return ST; } const AArch64TargetLowering *getTLI() const { return 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() { } } + // The mix of execute-only and non-execute-only at link time is + // non-execute-only. To avoid the empty implicitly created .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 (any_of(Asm, [](const MCSection &Sec) { + return cast<MCSectionELF>(Sec).getFlags() & ELF::SHF_AARCH64_PURECODE; + })) { + auto *Text = + static_cast<MCSectionELF *>(Ctx.getObjectFileInfo()->getTextSection()); + for (auto &F : *Text) + if (auto *DF = dyn_cast<MCDataFragment>(&F)) + if (!DF->getContents().empty()) + return; + Text->setFlags(Text->getFlags() | ELF::SHF_AARCH64_PURECODE); + } + MCSectionELF *MemtagSec = nullptr; for (const MCSymbol &Symbol : Asm.symbols()) { const auto &Sym = cast<MCSymbolELF>(Symbol); 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: + ret void +} + +; CHECK: .section .test,"axy",@progbits +; CHECK-NOT: .section +; CHECK-NOT: .text +; CHECK: .globl test_ExplicitSectionForGlobal +; CHECK: .type test_ExplicitSectionForGlobal,@function +define void @test_ExplicitSectionForGlobal() section ".test" { +entry: + ret void +} diff --git a/llvm/test/MC/ELF/AArch64/execute-only-populated-text-section.s b/llvm/test/MC/ELF/AArch64/execute-only-populated-text-section.... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/125688 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits