[llvm] [AArch64] Add support for SHF_AARCH64_PURECODE ELF section flag (1/3) (PR #125687)
Csanád Hajdú via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 13 01:19:11 PST 2025
https://github.com/Il-Capitano updated https://github.com/llvm/llvm-project/pull/125687
>From 6ff1cc4abb39b0526cae22497b5147cae35a7d6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Csan=C3=A1d=20Hajd=C3=BA?= <csanad.hajdu at arm.com>
Date: Tue, 4 Feb 2025 14:32:58 +0100
Subject: [PATCH 1/6] [AArch64] Add support for SHF_AARCH64_PURECODE ELF
section flag (1/3)
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.
Generating object files with the `SHF_AARCH64_PURECODE` flag set is
enabled by the `+execute-only` target feature.
---
llvm/include/llvm/BinaryFormat/ELF.h | 5 ++-
.../CodeGen/TargetLoweringObjectFileImpl.cpp | 13 +++---
llvm/lib/MC/MCParser/ELFAsmParser.cpp | 7 ++-
llvm/lib/MC/MCSectionELF.cpp | 3 ++
llvm/lib/ObjectYAML/ELFYAML.cpp | 3 ++
llvm/lib/Target/AArch64/AArch64Features.td | 5 +++
.../AArch64/AArch64TargetObjectFile.cpp | 26 +++++++++++
.../Target/AArch64/AArch64TargetObjectFile.h | 6 +++
.../AArch64/AArch64TargetTransformInfo.cpp | 17 +++++++-
.../AArch64/AArch64TargetTransformInfo.h | 2 +
.../MCTargetDesc/AArch64ELFStreamer.cpp | 18 ++++++++
.../CodeGen/AArch64/execute-only-section.ll | 21 +++++++++
.../execute-only-populated-text-section.s | 27 ++++++++++++
.../MC/ELF/AArch64/execute-only-section.s | 43 +++++++++++++++++++
.../AArch64/execute-only-text-section-data.s | 27 ++++++++++++
llvm/test/MC/ELF/section-flags-unknown.s | 3 ++
.../Inline/AArch64/inline-target-attr.ll | 25 +++++++++++
llvm/tools/llvm-readobj/ELFDumper.cpp | 8 ++++
18 files changed, 250 insertions(+), 9 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/execute-only-section.ll
create mode 100644 llvm/test/MC/ELF/AArch64/execute-only-populated-text-section.s
create mode 100644 llvm/test/MC/ELF/AArch64/execute-only-section.s
create mode 100644 llvm/test/MC/ELF/AArch64/execute-only-text-section-data.s
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 8853c4a88b0b5..a5979d029a9ea 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 3c2c7c8c9fed6..6cfebca9a4d57 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 b58210b3c268e..99b13c68a9966 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 25e62b70b5e2a..72a959b1c9208 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 539834fc8d4db..05e4d85b2ea5d 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 20db70ee38572..7c95ba662938d 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 8729fd4b802c8..434ae32502d48 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 0c822ac84f200..3e9cd51b742a2 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 a6edcf125782b..284278e34f8b4 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 b65e3c7a1ab20..481cb5511a331 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 6b5c5f36cbd4b..d29d383bc2312 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 0000000000000..15a270b07975e
--- /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", at progbits,unique,0
+; CHECK-NOT: .section
+; CHECK-NOT: .text
+; CHECK: .globl test_SectionForGlobal
+; CHECK: .type test_SectionForGlobal, at function
+define void @test_SectionForGlobal() {
+entry:
+ ret void
+}
+
+; CHECK: .section .test,"axy", at progbits
+; CHECK-NOT: .section
+; CHECK-NOT: .text
+; CHECK: .globl test_ExplicitSectionForGlobal
+; CHECK: .type test_ExplicitSectionForGlobal, at 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.s
new file mode 100644
index 0000000000000..b0ba8a18d52b3
--- /dev/null
+++ b/llvm/test/MC/ELF/AArch64/execute-only-populated-text-section.s
@@ -0,0 +1,27 @@
+// RUN: llvm-mc -filetype=obj -triple aarch64-unknown-linux-gnu %s -o - \
+// RUN: | llvm-readobj -S --symbols - | FileCheck %s
+
+ .text
+ ret
+
+ .section .text.foo,"axy"
+ ret
+
+// CHECK: Section {
+// CHECK: Name: .text
+// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT: Flags [ (0x6)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_EXECINSTR (0x4)
+// CHECK-NEXT: ]
+// CHECK: }
+
+// CHECK: Section {
+// CHECK: Name: .text.foo
+// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT: Flags [ (0x20000006)
+// CHECK-NEXT: SHF_AARCH64_PURECODE (0x20000000)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_EXECINSTR (0x4)
+// CHECK-NEXT: ]
+// CHECK: }
diff --git a/llvm/test/MC/ELF/AArch64/execute-only-section.s b/llvm/test/MC/ELF/AArch64/execute-only-section.s
new file mode 100644
index 0000000000000..6fd596376711d
--- /dev/null
+++ b/llvm/test/MC/ELF/AArch64/execute-only-section.s
@@ -0,0 +1,43 @@
+// RUN: llvm-mc -filetype=obj -triple aarch64-unknown-linux-gnu %s -o - \
+// RUN: | llvm-readobj -S --symbols - | FileCheck %s
+
+ .section .text,"axy", at progbits,unique,0
+ .globl foo
+ .p2align 2
+ .type foo, at function
+foo:
+ .cfi_startproc
+ ret
+.Lfunc_end0:
+ .size foo, .Lfunc_end0-foo
+ .cfi_endproc
+
+ .section ".note.GNU-stack","", at progbits
+
+
+// CHECK: Section {
+// CHECK: Name: .text
+// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT: Flags [ (0x20000006)
+// CHECK-NEXT: SHF_AARCH64_PURECODE (0x20000000)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_EXECINSTR (0x4)
+// CHECK-NEXT: ]
+// CHECK: Size: 0
+// CHECK: }
+
+// CHECK: Section {
+// CHECK: Name: .text
+// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT: Flags [ (0x20000006)
+// CHECK-NEXT: SHF_AARCH64_PURECODE (0x20000000)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_EXECINSTR (0x4)
+// CHECK-NEXT: ]
+// CHECK: Size: 2
+// CHECK: }
+
+// CHECK: Symbol {
+// CHECK: Name: foo
+// CHECK: Section: .text (0x3)
+// CHECK: }
diff --git a/llvm/test/MC/ELF/AArch64/execute-only-text-section-data.s b/llvm/test/MC/ELF/AArch64/execute-only-text-section-data.s
new file mode 100644
index 0000000000000..22bcffae67d0e
--- /dev/null
+++ b/llvm/test/MC/ELF/AArch64/execute-only-text-section-data.s
@@ -0,0 +1,27 @@
+// RUN: llvm-mc -filetype=obj -triple aarch64-unknown-linux-gnu %s -o - \
+// RUN: | llvm-readobj -S --symbols - | FileCheck %s
+
+ .text
+ .ascii "test"
+
+ .section .text.foo,"axy"
+ ret
+
+// CHECK: Section {
+// CHECK: Name: .text
+// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT: Flags [ (0x6)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_EXECINSTR (0x4)
+// CHECK-NEXT: ]
+// CHECK: }
+
+// CHECK: Section {
+// CHECK: Name: .text.foo
+// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT: Flags [ (0x20000006)
+// CHECK-NEXT: SHF_AARCH64_PURECODE (0x20000000)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_EXECINSTR (0x4)
+// CHECK-NEXT: ]
+// CHECK: }
diff --git a/llvm/test/MC/ELF/section-flags-unknown.s b/llvm/test/MC/ELF/section-flags-unknown.s
index 90c9185e8bfb1..b172403e34556 100644
--- a/llvm/test/MC/ELF/section-flags-unknown.s
+++ b/llvm/test/MC/ELF/section-flags-unknown.s
@@ -14,5 +14,8 @@
# CHECK: {{.*}}.s:[[# @LINE+1]]:30: error: unknown flag
.section SHF_ARM_PURECODE,"y", at progbits
+# CHECK: {{.*}}.s:[[# @LINE+1]]:34: error: unknown flag
+.section SHF_AARCH64_PURECODE,"y", at progbits
+
# CHECK: {{.*}}.s:[[# @LINE+1]]:30: error: unknown flag
.section SHF_X86_64_LARGE,"l", at progbits
diff --git a/llvm/test/Transforms/Inline/AArch64/inline-target-attr.ll b/llvm/test/Transforms/Inline/AArch64/inline-target-attr.ll
index 636f3c6600f8d..433a9c7bdd23b 100644
--- a/llvm/test/Transforms/Inline/AArch64/inline-target-attr.ll
+++ b/llvm/test/Transforms/Inline/AArch64/inline-target-attr.ll
@@ -27,6 +27,14 @@ entry:
; CHECK: call i32 @bar()
}
+define i32 @quux() #3 {
+entry:
+ %call = call i32 (...) @baz()
+ ret i32 %call
+; CHECK-LABEL: quux
+; CHECK: call i32 (...) @baz()
+}
+
define i32 @strict_align() #2 {
entry:
%call = call i32 @foo()
@@ -35,6 +43,23 @@ entry:
; CHECK: call i32 (...) @baz()
}
+define i32 @execute_only1() #3 {
+entry:
+ %call = call i32 @foo()
+ ret i32 %call
+; CHECK-LABEL: execute_only1
+; CHECK: call i32 @foo()
+}
+
+define i32 @execute_only2() #0 {
+entry:
+ %call = call i32 @quux()
+ ret i32 %call
+; CHECK-LABEL: execute_only2
+; CHECK: call i32 (...) @baz()
+}
+
attributes #0 = { "target-cpu"="generic" "target-features"="+crc,+neon" }
attributes #1 = { "target-cpu"="generic" "target-features"="+crc,+neon,+crypto" }
attributes #2 = { "target-cpu"="generic" "target-features"="+crc,+neon,+strict-align" }
+attributes #3 = { "target-cpu"="generic" "target-features"="+crc,+neon,+execute-only" }
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index bfca65aad52b4..78aaf79a61c46 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -1337,6 +1337,10 @@ const EnumEntry<unsigned> ElfXCoreSectionFlags[] = {
ENUM_ENT(XCORE_SHF_DP_SECTION, "")
};
+const EnumEntry<unsigned> ElfAArch64SectionFlags[] = {
+ ENUM_ENT(SHF_AARCH64_PURECODE, "y"),
+};
+
const EnumEntry<unsigned> ElfARMSectionFlags[] = {
ENUM_ENT(SHF_ARM_PURECODE, "y")
};
@@ -1375,6 +1379,10 @@ getSectionFlagsForTarget(unsigned EOSAbi, unsigned EMachine) {
break;
}
switch (EMachine) {
+ case EM_AARCH64:
+ Ret.insert(Ret.end(), std::begin(ElfAArch64SectionFlags),
+ std::end(ElfAArch64SectionFlags));
+ break;
case EM_ARM:
Ret.insert(Ret.end(), std::begin(ElfARMSectionFlags),
std::end(ElfARMSectionFlags));
>From f528eb788edb96b6d156292ea09422fe3102a2b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Csan=C3=A1d=20Hajd=C3=BA?= <csanad.hajdu at arm.com>
Date: Wed, 5 Feb 2025 12:34:40 +0100
Subject: [PATCH 2/6] Address review feedback from #125689
---
.../CodeGen/AArch64/execute-only-section.ll | 30 +++++++--
.../MC/ELF/AArch64/execute-only-section.s | 66 +++++++++++--------
llvm/test/MC/ELF/section-flags-unknown.s | 8 +--
3 files changed, 66 insertions(+), 38 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/execute-only-section.ll b/llvm/test/CodeGen/AArch64/execute-only-section.ll
index 15a270b07975e..182afd7479e3d 100644
--- a/llvm/test/CodeGen/AArch64/execute-only-section.ll
+++ b/llvm/test/CodeGen/AArch64/execute-only-section.ll
@@ -1,11 +1,23 @@
; RUN: llc -mtriple=aarch64 -mattr=+execute-only %s -o - | FileCheck %s
+$test_comdat = comdat any
+
; CHECK: .section .text,"axy", at progbits,unique,0
; CHECK-NOT: .section
; CHECK-NOT: .text
-; CHECK: .globl test_SectionForGlobal
-; CHECK: .type test_SectionForGlobal, at function
-define void @test_SectionForGlobal() {
+; CHECK: .globl test_section_for_global
+; CHECK: .type test_section_for_global, at function
+define void @test_section_for_global() {
+entry:
+ ret void
+}
+
+; CHECK: .section .text.test_comdat,"axGy", at progbits,test_comdat,comdat,unique,0
+; CHECK-NOT: .section
+; CHECK-NOT: .text
+; CHECK: .weak test_comdat
+; CHECK: .type test_comdat, at function
+define linkonce_odr void @test_comdat() comdat {
entry:
ret void
}
@@ -13,9 +25,15 @@ entry:
; CHECK: .section .test,"axy", at progbits
; CHECK-NOT: .section
; CHECK-NOT: .text
-; CHECK: .globl test_ExplicitSectionForGlobal
-; CHECK: .type test_ExplicitSectionForGlobal, at function
-define void @test_ExplicitSectionForGlobal() section ".test" {
+; CHECK: .globl test_explicit_section_for_global
+; CHECK: .type test_explicit_section_for_global, at function
+define void @test_explicit_section_for_global() section ".test" {
entry:
ret void
}
+
+; CHECK: .rodata,"a", at progbits
+; CHECK-NOT: .section
+; CHECK-NOT: .text
+; CHECK: .globl test_rodata
+ at test_rodata = constant i32 0, align 4
diff --git a/llvm/test/MC/ELF/AArch64/execute-only-section.s b/llvm/test/MC/ELF/AArch64/execute-only-section.s
index 6fd596376711d..1699a14740c62 100644
--- a/llvm/test/MC/ELF/AArch64/execute-only-section.s
+++ b/llvm/test/MC/ELF/AArch64/execute-only-section.s
@@ -1,5 +1,7 @@
// RUN: llvm-mc -filetype=obj -triple aarch64-unknown-linux-gnu %s -o - \
-// RUN: | llvm-readobj -S --symbols - | FileCheck %s
+// RUN: | llvm-readobj -S --symbols - | FileCheck %s --check-prefix=READOBJ
+// RUN: llvm-mc -filetype=obj -triple aarch64-unknown-linux-gnu %s -o - \
+// RUN: | llvm-readelf -S --symbols - | FileCheck %s --check-prefix=READELF
.section .text,"axy", at progbits,unique,0
.globl foo
@@ -12,32 +14,42 @@ foo:
.size foo, .Lfunc_end0-foo
.cfi_endproc
- .section ".note.GNU-stack","", at progbits
-
+// READOBJ: Section {
+// READOBJ: Name: .text
+// READOBJ-NEXT: Type: SHT_PROGBITS (0x1)
+// READOBJ-NEXT: Flags [ (0x20000006)
+// READOBJ-NEXT: SHF_AARCH64_PURECODE (0x20000000)
+// READOBJ-NEXT: SHF_ALLOC (0x2)
+// READOBJ-NEXT: SHF_EXECINSTR (0x4)
+// READOBJ-NEXT: ]
+// READOBJ-NEXT: Address:
+// READOBJ-NEXT: Offset:
+// READOBJ-NEXT: Size: 0
+// READOBJ: }
-// CHECK: Section {
-// CHECK: Name: .text
-// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
-// CHECK-NEXT: Flags [ (0x20000006)
-// CHECK-NEXT: SHF_AARCH64_PURECODE (0x20000000)
-// CHECK-NEXT: SHF_ALLOC (0x2)
-// CHECK-NEXT: SHF_EXECINSTR (0x4)
-// CHECK-NEXT: ]
-// CHECK: Size: 0
-// CHECK: }
+// READOBJ: Section {
+// READOBJ: Name: .text
+// READOBJ-NEXT: Type: SHT_PROGBITS (0x1)
+// READOBJ-NEXT: Flags [ (0x20000006)
+// READOBJ-NEXT: SHF_AARCH64_PURECODE (0x20000000)
+// READOBJ-NEXT: SHF_ALLOC (0x2)
+// READOBJ-NEXT: SHF_EXECINSTR (0x4)
+// READOBJ-NEXT: ]
+// READOBJ-NEXT: Address:
+// READOBJ-NEXT: Offset:
+// READOBJ-NEXT: Size: 4
+// READOBJ: }
-// CHECK: Section {
-// CHECK: Name: .text
-// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
-// CHECK-NEXT: Flags [ (0x20000006)
-// CHECK-NEXT: SHF_AARCH64_PURECODE (0x20000000)
-// CHECK-NEXT: SHF_ALLOC (0x2)
-// CHECK-NEXT: SHF_EXECINSTR (0x4)
-// CHECK-NEXT: ]
-// CHECK: Size: 2
-// CHECK: }
+// READOBJ: Symbol {
+// READOBJ: Name: foo
+// READOBJ-NEXT: Value:
+// READOBJ-NEXT: Size: 4
+// READOBJ-NEXT: Binding: Global
+// READOBJ-NEXT: Type: Function
+// READOBJ-NEXT: Other:
+// READOBJ-NEXT: Section: .text
+// READOBJ: }
-// CHECK: Symbol {
-// CHECK: Name: foo
-// CHECK: Section: .text (0x3)
-// CHECK: }
+// READELF: Section Headers:
+// READELF: .text PROGBITS {{[0-9a-f]+}} {{[0-9a-f]+}} 000000 {{[0-9a-f]+}} AXy {{[0-9]+}} {{[0-9]+}} {{[0-9]+}}
+// READELF: .text PROGBITS {{[0-9a-f]+}} {{[0-9a-f]+}} 000004 {{[0-9a-f]+}} AXy {{[0-9]+}} {{[0-9]+}} {{[0-9]+}}
diff --git a/llvm/test/MC/ELF/section-flags-unknown.s b/llvm/test/MC/ELF/section-flags-unknown.s
index b172403e34556..5dca55f25658c 100644
--- a/llvm/test/MC/ELF/section-flags-unknown.s
+++ b/llvm/test/MC/ELF/section-flags-unknown.s
@@ -11,11 +11,9 @@
# CHECK: {{.*}}.s:[[# @LINE+1]]:27: error: unknown flag
.section SHF_HEX_GPREL,"s", at progbits
-# CHECK: {{.*}}.s:[[# @LINE+1]]:30: error: unknown flag
-.section SHF_ARM_PURECODE,"y", at progbits
-
-# CHECK: {{.*}}.s:[[# @LINE+1]]:34: error: unknown flag
-.section SHF_AARCH64_PURECODE,"y", at progbits
+## Test SHF_ARM_PURECODE and SHF_AARCH64_PURECODE section flags
+# CHECK: {{.*}}.s:[[# @LINE+1]]:22: error: unknown flag
+.section purecode,"y", at progbits
# CHECK: {{.*}}.s:[[# @LINE+1]]:30: error: unknown flag
.section SHF_X86_64_LARGE,"l", at progbits
>From 25c34c03e9886afb3d7f17b56968cd1bc6176036 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Csan=C3=A1d=20Hajd=C3=BA?= <csanad.hajdu at arm.com>
Date: Wed, 12 Feb 2025 10:39:38 +0100
Subject: [PATCH 3/6] Change formatting of `ElfAArch64SectionFlags`
---
llvm/tools/llvm-readobj/ELFDumper.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 78aaf79a61c46..dba0527b7784a 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -1338,7 +1338,7 @@ const EnumEntry<unsigned> ElfXCoreSectionFlags[] = {
};
const EnumEntry<unsigned> ElfAArch64SectionFlags[] = {
- ENUM_ENT(SHF_AARCH64_PURECODE, "y"),
+ ENUM_ENT(SHF_AARCH64_PURECODE, "y")
};
const EnumEntry<unsigned> ElfARMSectionFlags[] = {
>From 2c47c28fb8e1f3b365db971d55ea898c8307954f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Csan=C3=A1d=20Hajd=C3=BA?= <csanad.hajdu at arm.com>
Date: Wed, 12 Feb 2025 10:42:21 +0100
Subject: [PATCH 4/6] Add tests for `llvm-readobj` and `llvm-objcopy`
---
.../ELF/rename-section-flag-osproc-mask.test | 25 +++++++++++++++++++
.../tools/llvm-readobj/ELF/gnu-sections.test | 12 +++++++++
.../llvm-readobj/ELF/section-arch-flags.test | 22 ++++++++++++++++
3 files changed, 59 insertions(+)
diff --git a/llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-osproc-mask.test b/llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-osproc-mask.test
index 6141f797ecd49..51a01f3f6712a 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-osproc-mask.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-osproc-mask.test
@@ -121,3 +121,28 @@ Sections:
# ARM-NEXT: SHF_ARM_PURECODE (0x20000000)
# ARM-NEXT: SHF_WRITE (0x1)
# ARM-NEXT: ]
+
+# ===== aarch64 =====
+
+# RUN: yaml2obj --docnum=5 %s -o %t-aarch64.o
+# RUN: llvm-objcopy --rename-section=.foo=.bar,alloc %t-aarch64.o
+# RUN: llvm-readobj --sections %t-aarch64.o | FileCheck %s --check-prefix=AARCH64
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_AARCH64
+Sections:
+ - Name: .foo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_AARCH64_PURECODE ]
+
+# AARCH64: Name: .bar
+# AARCH64-NEXT: Type: SHT_PROGBITS
+# AARCH64-NEXT: Flags [
+# AARCH64-NEXT: SHF_AARCH64_PURECODE (0x20000000)
+# AARCH64-NEXT: SHF_ALLOC (0x2)
+# AARCH64-NEXT: SHF_WRITE (0x1)
+# AARCH64-NEXT: ]
diff --git a/llvm/test/tools/llvm-readobj/ELF/gnu-sections.test b/llvm/test/tools/llvm-readobj/ELF/gnu-sections.test
index 02d082329c3d8..cec5d6cf7f4c5 100644
--- a/llvm/test/tools/llvm-readobj/ELF/gnu-sections.test
+++ b/llvm/test/tools/llvm-readobj/ELF/gnu-sections.test
@@ -110,3 +110,15 @@ Symbols:
# ARM-NEXT: L (link order), O (extra OS processing required), G (group), T (TLS),
# ARM-NEXT: C (compressed), x (unknown), o (OS specific), E (exclude),
# ARM-NEXT: R (retain), y (purecode), p (processor specific)
+
+## For an EM_AARCH64 target we print "y" for the SHF_AARCH64_PURECODE section flag.
+## Check we mention it in the flag key.
+
+# RUN: yaml2obj -DMACHINE=EM_AARCH64 %s -o %t-aarch64.o
+# RUN: llvm-readelf -S %t-arm.o | FileCheck %s --check-prefix=AARCH64 --strict-whitespace --match-full-lines
+
+# AARCH64:Key to Flags:
+# AARCH64-NEXT: W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
+# AARCH64-NEXT: L (link order), O (extra OS processing required), G (group), T (TLS),
+# AARCH64-NEXT: C (compressed), x (unknown), o (OS specific), E (exclude),
+# AARCH64-NEXT: R (retain), y (purecode), p (processor specific)
diff --git a/llvm/test/tools/llvm-readobj/ELF/section-arch-flags.test b/llvm/test/tools/llvm-readobj/ELF/section-arch-flags.test
index f6c74a6a44177..19bf9973489a6 100644
--- a/llvm/test/tools/llvm-readobj/ELF/section-arch-flags.test
+++ b/llvm/test/tools/llvm-readobj/ELF/section-arch-flags.test
@@ -138,3 +138,25 @@ Sections:
- Name: foo
Type: SHT_PROGBITS
Flags: [ SHF_ARM_PURECODE ]
+
+# RUN: yaml2obj --docnum 6 %s -o %t-aarch64.o
+# RUN: llvm-readobj -S %t-aarch64.o | FileCheck --check-prefix=AARCH64-LLVM %s
+# RUN: llvm-readelf -S %t-aarch64.o | FileCheck --check-prefix=AARCH64-GNU %s
+
+# AARCH64-LLVM: Flags [ (0x20000000)
+# AARCH64-LLVM-NEXT: SHF_AARCH64_PURECODE (0x20000000)
+# AARCH64-LLVM-NEXT: ]
+
+# AARCH64-GNU: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
+# AARCH64-GNU: [ 1] foo PROGBITS 0000000000000000 000040 000000 00 y 0 0 0
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_AARCH64
+Sections:
+ - Name: foo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_AARCH64_PURECODE ]
>From 835a8003fb6444ed6a7202c825ba0da64003e68a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Csan=C3=A1d=20Hajd=C3=BA?= <csanad.hajdu at arm.com>
Date: Wed, 12 Feb 2025 17:31:46 +0100
Subject: [PATCH 5/6] Address review feedback
---
llvm/include/llvm/BinaryFormat/ELF.h | 2 +-
llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 11 ++++++-----
.../lib/Target/AArch64/AArch64TargetTransformInfo.cpp | 3 ++-
3 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index a5979d029a9ea..d4c3c21078ea6 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1299,7 +1299,7 @@ enum : unsigned {
// Section data is string data by default.
SHF_MIPS_STRING = 0x80000000,
- // Make code section unreadable when in execute-only mode
+ // Section contains only program instructions and no program data.
SHF_ARM_PURECODE = 0x20000000,
// Section contains only program instructions and no program data.
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 6cfebca9a4d57..ea5df42ccc7d9 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -559,11 +559,12 @@ static unsigned getELFSectionFlags(SectionKind K, const Triple &T) {
if (K.isText())
Flags |= ELF::SHF_EXECINSTR;
- if ((T.isARM() || T.isThumb()) && K.isExecuteOnly())
- Flags |= ELF::SHF_ARM_PURECODE;
-
- if (T.isAArch64() && K.isExecuteOnly())
- Flags |= ELF::SHF_AARCH64_PURECODE;
+ if (K.isExecuteOnly()) {
+ if (T.isAArch64())
+ Flags |= ELF::SHF_AARCH64_PURECODE;
+ else if (T.isARM() || T.isThumb())
+ Flags |= ELF::SHF_ARM_PURECODE;
+ }
if (K.isWriteable())
Flags |= ELF::SHF_WRITE;
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 284278e34f8b4..cb566c773a064 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -295,7 +295,8 @@ bool AArch64TTIImpl::areInlineCompatible(const Function *Caller,
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".
+ // for example a "+execute-only" callee can be inlined into a caller without
+ // "+execute-only", but not vice versa.
FeatureBitset EffectiveCallerBits = CallerBits ^ InlineInverseFeatures;
FeatureBitset EffectiveCalleeBits = CalleeBits ^ InlineInverseFeatures;
>From 810e38d36ca097ae76f2e46657d78ff4f4a288f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Csan=C3=A1d=20Hajd=C3=BA?= <csanad.hajdu at arm.com>
Date: Thu, 13 Feb 2025 10:11:14 +0100
Subject: [PATCH 6/6] Bugfix in `llvm-readelf` Key to Flags output
---
.../tools/llvm-readobj/ELF/gnu-sections.test | 26 ++++++-------------
llvm/tools/llvm-readobj/ELFDumper.cpp | 2 +-
2 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/llvm/test/tools/llvm-readobj/ELF/gnu-sections.test b/llvm/test/tools/llvm-readobj/ELF/gnu-sections.test
index cec5d6cf7f4c5..25eeee5a95919 100644
--- a/llvm/test/tools/llvm-readobj/ELF/gnu-sections.test
+++ b/llvm/test/tools/llvm-readobj/ELF/gnu-sections.test
@@ -99,26 +99,16 @@ Symbols:
# ELF64-NEXT: C (compressed), x (unknown), o (OS specific), E (exclude),
# ELF64-NEXT: R (retain), l (large), p (processor specific)
-## For an EM_ARM target we print "y" for the SHF_ARM_PURECODE section flag.
+## For an EM_ARM or EM_AARCH64 target we print "y" for the PURECODE section flag.
## Check we mention it in the flag key.
# RUN: yaml2obj -DMACHINE=EM_ARM %s -o %t-arm.o
-# RUN: llvm-readelf -S %t-arm.o | FileCheck %s --check-prefix=ARM --strict-whitespace --match-full-lines
-
-# ARM:Key to Flags:
-# ARM-NEXT: W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
-# ARM-NEXT: L (link order), O (extra OS processing required), G (group), T (TLS),
-# ARM-NEXT: C (compressed), x (unknown), o (OS specific), E (exclude),
-# ARM-NEXT: R (retain), y (purecode), p (processor specific)
-
-## For an EM_AARCH64 target we print "y" for the SHF_AARCH64_PURECODE section flag.
-## Check we mention it in the flag key.
-
+# RUN: llvm-readelf -S %t-arm.o | FileCheck %s --check-prefix=PURECODE --strict-whitespace --match-full-lines
# RUN: yaml2obj -DMACHINE=EM_AARCH64 %s -o %t-aarch64.o
-# RUN: llvm-readelf -S %t-arm.o | FileCheck %s --check-prefix=AARCH64 --strict-whitespace --match-full-lines
+# RUN: llvm-readelf -S %t-aarch64.o | FileCheck %s --check-prefix=PURECODE --strict-whitespace --match-full-lines
-# AARCH64:Key to Flags:
-# AARCH64-NEXT: W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
-# AARCH64-NEXT: L (link order), O (extra OS processing required), G (group), T (TLS),
-# AARCH64-NEXT: C (compressed), x (unknown), o (OS specific), E (exclude),
-# AARCH64-NEXT: R (retain), y (purecode), p (processor specific)
+# PURECODE:Key to Flags:
+# PURECODE-NEXT: W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
+# PURECODE-NEXT: L (link order), O (extra OS processing required), G (group), T (TLS),
+# PURECODE-NEXT: C (compressed), x (unknown), o (OS specific), E (exclude),
+# PURECODE-NEXT: R (retain), y (purecode), p (processor specific)
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index dba0527b7784a..a484a897b8df4 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -4112,7 +4112,7 @@ static void printSectionDescription(formatted_raw_ostream &OS,
if (EMachine == EM_X86_64)
OS << ", l (large)";
- else if (EMachine == EM_ARM)
+ else if (EMachine == EM_ARM || EMachine == EM_AARCH64)
OS << ", y (purecode)";
OS << ", p (processor specific)\n";
More information about the llvm-commits
mailing list