Skip to content

[Clang][AArch64] Add support for SHF_AARCH64_PURECODE ELF section flag (2/3) #125688

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4725,9 +4725,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. "
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ static void getAArch64MultilibFlags(const Driver &D,
const llvm::opt::ArgList &Args,
Multilib::flags_list &Result) {
std::vector<StringRef> Features;
tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, false);
tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features,
/*ForAS=*/false,
/*ForMultilib=*/true);
const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
UnifiedFeatures.end());
Expand Down
15 changes: 14 additions & 1 deletion clang/lib/Driver/ToolChains/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
const llvm::Triple &Triple,
const ArgList &Args,
std::vector<StringRef> &Features,
bool ForAS) {
bool ForAS, bool ForMultilib) {
Arg *A;
bool success = true;
llvm::StringRef WaMArch;
Expand Down Expand Up @@ -332,6 +332,19 @@ 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.
// It's not needed for multilib selection and may hide an unused
// argument diagnostic if the code is always run.
if (!ForAS && !ForMultilib) {
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");

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Arch/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace aarch64 {
void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features,
bool ForAS);
bool ForAS, bool ForMultilib = false);

std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple, llvm::opt::Arg *&A);
Expand Down
19 changes: 19 additions & 0 deletions clang/test/CodeGen/aarch64-execute-only.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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() {}
9 changes: 9 additions & 0 deletions clang/test/Driver/aarch64-execute-only.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// 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
// RUN: %clang -### --multi-lib-config=%S/Inputs/multilib/empty.yaml --sysroot= \
// RUN: --target=aarch64-none-elf -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'
11 changes: 8 additions & 3 deletions clang/test/Driver/fsanitize.c
Original file line number Diff line number Diff line change
Expand Up @@ -1053,21 +1053,26 @@
// 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
// RUN: not %clang --target=armv6t2-eabi -mexecute-only -fsanitize=kcfi %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-KCFI-MEXECUTE-ONLY
// 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: %clang --target=armv6t2-eabi -mexecute-only -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-UNDEFINED

// 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-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),?){17}"}}
// 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}"}}

// * Test BareMetal toolchain sanitizer support *

Expand Down