[clang] 850defb - Add assembler plumbing for sanitize_memtag
Mitch Phillips via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 1 10:51:03 PST 2022
Author: Mitch Phillips
Date: 2022-12-01T10:50:34-08:00
New Revision: 850defb86164f1a68816b21f31529d871400a454
URL: https://github.com/llvm/llvm-project/commit/850defb86164f1a68816b21f31529d871400a454
DIFF: https://github.com/llvm/llvm-project/commit/850defb86164f1a68816b21f31529d871400a454.diff
LOG: Add assembler plumbing for sanitize_memtag
Extends the Asm reader/writer to support reading and writing the
'.memtag' directive (including allowing it on internal global
variables). Also add some extra tooling support, including objdump and
yaml2obj/obj2yaml.
Test that the sanitize_memtag IR attribute produces the expected asm
directive.
Uses the new Aarch64 MemtagABI specification
(https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst)
to identify symbols as tagged in object files. This is done using a
R_AARCH64_NONE relocation that identifies each tagged symbol, and these
relocations are tagged in a special SHT_AARCH64_MEMTAG_GLOBALS_STATIC
section. This signals to the linker that the global variable should be
tagged.
Reviewed By: fmayer, MaskRay, peter.smith
Differential Revision: https://reviews.llvm.org/D128958
Added:
clang/test/Driver/memtag-stack_lto.c
llvm/test/MC/AArch64/global-tagging.ll
Modified:
clang/test/Driver/memtag-stack.c
llvm/include/llvm/BinaryFormat/ELF.h
llvm/include/llvm/MC/MCAsmInfo.h
llvm/include/llvm/MC/MCDirectives.h
llvm/include/llvm/MC/MCELFObjectWriter.h
llvm/include/llvm/MC/MCSymbolELF.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/MC/ELFObjectWriter.cpp
llvm/lib/MC/MCAsmStreamer.cpp
llvm/lib/MC/MCELFStreamer.cpp
llvm/lib/MC/MCMachOStreamer.cpp
llvm/lib/MC/MCParser/AsmParser.cpp
llvm/lib/MC/MCSymbolELF.cpp
llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
Removed:
clang/test/Driver/memtag_lto.c
################################################################################
diff --git a/clang/test/Driver/memtag-stack.c b/clang/test/Driver/memtag-stack.c
index 9f22f6687f86..58003fd1b02b 100644
--- a/clang/test/Driver/memtag-stack.c
+++ b/clang/test/Driver/memtag-stack.c
@@ -1,7 +1,7 @@
-// RUN: %clang -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -mllvm -stack-safety-print=1 %s -S -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SAFETY
-// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -mllvm -stack-safety-print=1 %s -S -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SAFETY
-// RUN: %clang -O2 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -mllvm -stack-safety-print=1 %s -S -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SAFETY
-// RUN: %clang -O3 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -mllvm -stack-safety-print=1 %s -S -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SAFETY
+// RUN: %clang -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag-stack -mllvm -stack-safety-print=1 %s -S -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SAFETY
+// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag-stack -mllvm -stack-safety-print=1 %s -S -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SAFETY
+// RUN: %clang -O2 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag-stack -mllvm -stack-safety-print=1 %s -S -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SAFETY
+// RUN: %clang -O3 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag-stack -mllvm -stack-safety-print=1 %s -S -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SAFETY
// REQUIRES: aarch64-registered-target
diff --git a/clang/test/Driver/memtag_lto.c b/clang/test/Driver/memtag-stack_lto.c
similarity index 85%
rename from clang/test/Driver/memtag_lto.c
rename to clang/test/Driver/memtag-stack_lto.c
index 2ad22141608c..2fe15a119d2a 100644
--- a/clang/test/Driver/memtag_lto.c
+++ b/clang/test/Driver/memtag-stack_lto.c
@@ -33,14 +33,14 @@
// RUN: rm -f %t*
// -O0: both are unsafe.
-// RUN: %clang -O0 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -mllvm -stack-safety-print %s -S -o - 2>&1 | FileCheck %s
+// RUN: %clang -O0 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag-stack -mllvm -stack-safety-print %s -S -o - 2>&1 | FileCheck %s
// No LTO: just one is safe.
-// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -mllvm -stack-safety-print %s -S -o /dev/null 2>&1 | FileCheck %s -check-prefixes=SSI,XUNSAFE,YSAFE
+// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag-stack -mllvm -stack-safety-print %s -S -o /dev/null 2>&1 | FileCheck %s -check-prefixes=SSI,XUNSAFE,YSAFE
// Full LTO: both are safe.
-// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm1.bc
-// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm2.bc
+// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag-stack -c %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm1.bc
+// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag-stack -c -DBUILD2 %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm2.bc
// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
// RUN: -r %t.ltonewpm1.bc,fn,plx \
// RUN: -r %t.ltonewpm1.bc,use,lx \
@@ -50,8 +50,8 @@
// RUN: -r %t.ltonewpm2.bc,z, 2>&1 | FileCheck %s -check-prefixes=SSI,XSAFE,YSAFE
// Thin LTO: both are safe.
-// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm1.bc
-// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm2.bc
+// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag-stack -c %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm1.bc
+// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag-stack -c -DBUILD2 %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm2.bc
// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
// RUN: -r %t.thinltonewpm1.bc,fn,plx \
// RUN: -r %t.thinltonewpm1.bc,use,lx \
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 9f6b00ba4a65..bdeb68c27592 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1035,6 +1035,10 @@ enum : unsigned {
SHT_ARM_ATTRIBUTES = 0x70000003U,
SHT_ARM_DEBUGOVERLAY = 0x70000004U,
SHT_ARM_OVERLAYSECTION = 0x70000005U,
+ // Special aarch64-specific sections for MTE support, as described in:
+ // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#7section-types
+ SHT_AARCH64_MEMTAG_GLOBALS_STATIC = 0x70000007U,
+ SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC = 0x70000008U,
SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in
// this section based on their sizes
SHT_X86_64_UNWIND = 0x70000001, // Unwind information
diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index ec17131e17e8..ab8c36a412fc 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -442,6 +442,8 @@ class MCAsmInfo {
/// protected visibility. Defaults to MCSA_Protected
MCSymbolAttr ProtectedVisibilityAttr = MCSA_Protected;
+ MCSymbolAttr MemtagAttr = MCSA_Memtag;
+
//===--- Dwarf Emission Directives -----------------------------------===//
/// True if target supports emission of debugging information. Defaults to
@@ -772,6 +774,8 @@ class MCAsmInfo {
return ProtectedVisibilityAttr;
}
+ MCSymbolAttr getMemtagAttr() const { return MemtagAttr; }
+
bool doesSupportDebugInformation() const { return SupportsDebugInformation; }
ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; }
diff --git a/llvm/include/llvm/MC/MCDirectives.h b/llvm/include/llvm/MC/MCDirectives.h
index d6ab29febeeb..b9668a0c994f 100644
--- a/llvm/include/llvm/MC/MCDirectives.h
+++ b/llvm/include/llvm/MC/MCDirectives.h
@@ -45,7 +45,8 @@ enum MCSymbolAttr {
MCSA_Weak, ///< .weak
MCSA_WeakDefinition, ///< .weak_definition (MachO)
MCSA_WeakReference, ///< .weak_reference (MachO)
- MCSA_WeakDefAutoPrivate ///< .weak_def_can_be_hidden (MachO)
+ MCSA_WeakDefAutoPrivate, ///< .weak_def_can_be_hidden (MachO)
+ MCSA_Memtag, ///< .memtag (ELF)
};
enum MCAssemblerFlag {
diff --git a/llvm/include/llvm/MC/MCELFObjectWriter.h b/llvm/include/llvm/MC/MCELFObjectWriter.h
index fa17759bc21a..5a5238942e80 100644
--- a/llvm/include/llvm/MC/MCELFObjectWriter.h
+++ b/llvm/include/llvm/MC/MCELFObjectWriter.h
@@ -139,6 +139,14 @@ class MCELFObjectTargetWriter : public MCObjectTargetWriter {
unsigned setRSsym(unsigned Value, unsigned Type) const {
return (Type & R_SSYM_MASK) | ((Value & 0xff) << R_SSYM_SHIFT);
}
+
+ // On AArch64, return a new section to be added to the ELF object that
+ // contains relocations used to describe every symbol that should have memory
+ // tags applied. Returns nullptr if no such section is necessary (i.e. there's
+ // no tagged globals).
+ virtual MCSectionELF *getMemtagRelocsSection(MCContext &Ctx) const {
+ return nullptr;
+ }
};
/// Construct a new ELF writer instance.
diff --git a/llvm/include/llvm/MC/MCSymbolELF.h b/llvm/include/llvm/MC/MCSymbolELF.h
index 34e5c4344aff..9fc49ea322ce 100644
--- a/llvm/include/llvm/MC/MCSymbolELF.h
+++ b/llvm/include/llvm/MC/MCSymbolELF.h
@@ -43,6 +43,9 @@ class MCSymbolELF : public MCSymbol {
void setIsSignature() const;
bool isSignature() const;
+ void setMemtag(bool Tagged);
+ bool isMemtag() const;
+
static bool classof(const MCSymbol *S) { return S->isELF(); }
private:
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 414bed41d80f..1d148cd7b11b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -712,6 +712,16 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
// GV's or GVSym's attributes will be used for the EmittedSym.
emitVisibility(EmittedSym, GV->getVisibility(), !GV->isDeclaration());
+ if (GV->isTagged()) {
+ Triple T = TM.getTargetTriple();
+
+ if (T.getArch() != Triple::aarch64 || !T.isAndroid())
+ OutContext.reportError(SMLoc(),
+ "Tagged symbols (-fsanitize=memtag-globals) are "
+ "only supported on aarch64 + Android.");
+ OutStreamer->emitSymbolAttribute(EmittedSym, MAI->getMemtagAttr());
+ }
+
if (!GV->hasInitializer()) // External globals require no extra code.
return;
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 3dc059923687..4cbe01ce1b0e 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -192,6 +192,8 @@ struct ELFWriter {
MCSectionELF *createRelocationSection(MCContext &Ctx,
const MCSectionELF &Sec);
+ void createMemtagRelocs(MCAssembler &Asm);
+
void writeSectionHeader(const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap,
const SectionOffsetsTy &SectionOffsets);
@@ -609,6 +611,23 @@ bool ELFWriter::isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
return true;
}
+void ELFWriter::createMemtagRelocs(MCAssembler &Asm) {
+ MCSectionELF *MemtagRelocs = nullptr;
+ for (const MCSymbol &Sym : Asm.symbols()) {
+ const auto &SymE = cast<MCSymbolELF>(Sym);
+ if (!SymE.isMemtag())
+ continue;
+ if (MemtagRelocs == nullptr) {
+ MemtagRelocs = OWriter.TargetObjectWriter->getMemtagRelocsSection(Asm.getContext());
+ if (MemtagRelocs == nullptr)
+ report_fatal_error("Tagged globals are not available on this architecture.");
+ Asm.registerSection(*MemtagRelocs);
+ }
+ ELFRelocationEntry Rec(0, &SymE, ELF::R_AARCH64_NONE, 0, nullptr, 0);
+ OWriter.Relocations[MemtagRelocs].push_back(Rec);
+ }
+}
+
void ELFWriter::computeSymbolTable(
MCAssembler &Asm, const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap,
@@ -1068,6 +1087,8 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
StringTableIndex = addToSectionTable(StrtabSection);
+ createMemtagRelocs(Asm);
+
RevGroupMapTy RevGroupMap;
SectionIndexMapTy SectionIndexMap;
@@ -1317,6 +1338,15 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
if (Sym->isUndefined())
return true;
+ // For memory-tagged symbols, ensure that the relocation uses the symbol. For
+ // tagged symbols, we emit an empty relocation (R_AARCH64_NONE) in a special
+ // section (SHT_AARCH64_MEMTAG_GLOBALS_STATIC) to indicate to the linker that
+ // this global needs to be tagged. In addition, the linker needs to know
+ // whether to emit a special addend when relocating `end` symbols, and this
+ // can only be determined by the attributes of the symbol itself.
+ if (Sym->isMemtag())
+ return true;
+
unsigned Binding = Sym->getBinding();
switch(Binding) {
default:
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index bd939225c094..effa5221afc3 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -769,6 +769,9 @@ bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
case MCSA_Exported:
// Non-AIX assemblers currently do not support exported visibility.
return false;
+ case MCSA_Memtag:
+ OS << "\t.memtag\t";
+ break;
}
Symbol->print(OS, MAI);
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 60e997cbb682..962ed989537e 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -287,6 +287,10 @@ bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
Symbol->setVisibility(ELF::STV_PROTECTED);
break;
+ case MCSA_Memtag:
+ Symbol->setMemtag(true);
+ break;
+
case MCSA_Hidden:
Symbol->setVisibility(ELF::STV_HIDDEN);
break;
diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index a807439cced5..a1cbc99068f1 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -358,6 +358,7 @@ bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,
case MCSA_Local:
case MCSA_LGlobal:
case MCSA_Exported:
+ case MCSA_Memtag:
return false;
case MCSA_Global:
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 1f6f98e50207..b85f76096bf8 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -539,6 +539,7 @@ class AsmParser : public MCAsmParser {
DK_LTO_DISCARD,
DK_LTO_SET_CONDITIONAL,
DK_CFI_MTE_TAGGED_FRAME,
+ DK_MEMTAG,
DK_END
};
@@ -2298,6 +2299,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectivePseudoProbe();
case DK_LTO_DISCARD:
return parseDirectiveLTODiscard();
+ case DK_MEMTAG:
+ return parseDirectiveSymbolAttribute(MCSA_Memtag);
}
return Error(IDLoc, "unknown directive");
@@ -4984,8 +4987,9 @@ bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- // Assembler local symbols don't make any sense here. Complain loudly.
- if (Sym->isTemporary())
+ // Assembler local symbols don't make any sense here, except for directives
+ // that the symbol should be tagged.
+ if (Sym->isTemporary() && Attr != MCSA_Memtag)
return Error(Loc, "non-local symbol required");
if (!getStreamer().emitSymbolAttribute(Sym, Attr))
@@ -5598,6 +5602,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;
DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;
DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL;
+ DirectiveKindMap[".memtag"] = DK_MEMTAG;
}
MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
diff --git a/llvm/lib/MC/MCSymbolELF.cpp b/llvm/lib/MC/MCSymbolELF.cpp
index 820a91f57c17..5a3814867e3d 100644
--- a/llvm/lib/MC/MCSymbolELF.cpp
+++ b/llvm/lib/MC/MCSymbolELF.cpp
@@ -33,7 +33,10 @@ enum {
ELF_WeakrefUsedInReloc_Shift = 11,
// One bit.
- ELF_BindingSet_Shift = 12
+ ELF_BindingSet_Shift = 12,
+
+ // One bit.
+ ELF_IsMemoryTagged_Shift = 13,
};
}
@@ -193,4 +196,16 @@ void MCSymbolELF::setIsBindingSet() const {
bool MCSymbolELF::isBindingSet() const {
return getFlags() & (0x1 << ELF_BindingSet_Shift);
}
+
+bool MCSymbolELF::isMemtag() const {
+ return getFlags() & (0x1 << ELF_IsMemoryTagged_Shift);
+}
+
+void MCSymbolELF::setMemtag(bool Tagged) {
+ uint32_t OtherFlags = getFlags() & ~(1 << ELF_IsMemoryTagged_Shift);
+ if (Tagged)
+ setFlags(OtherFlags | (1 << ELF_IsMemoryTagged_Shift));
+ else
+ setFlags(OtherFlags);
+}
}
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index 2f9c17245b5f..bcb6c7c1a0fa 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -34,6 +34,8 @@ class AArch64ELFObjectWriter : public MCELFObjectTargetWriter {
~AArch64ELFObjectWriter() override = default;
+ MCSectionELF *getMemtagRelocsSection(MCContext &Ctx) const override;
+
protected:
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup, bool IsPCRel) const override;
@@ -453,6 +455,12 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
llvm_unreachable("Unimplemented fixup -> relocation");
}
+MCSectionELF *
+AArch64ELFObjectWriter::getMemtagRelocsSection(MCContext &Ctx) const {
+ return Ctx.getELFSection(".memtag.globals.static",
+ ELF::SHT_AARCH64_MEMTAG_GLOBALS_STATIC, 0);
+}
+
std::unique_ptr<MCObjectTargetWriter>
llvm::createAArch64ELFObjectWriter(uint8_t OSABI, bool IsILP32) {
return std::make_unique<AArch64ELFObjectWriter>(OSABI, IsILP32);
diff --git a/llvm/test/MC/AArch64/global-tagging.ll b/llvm/test/MC/AArch64/global-tagging.ll
new file mode 100644
index 000000000000..871c6fd0c39e
--- /dev/null
+++ b/llvm/test/MC/AArch64/global-tagging.ll
@@ -0,0 +1,46 @@
+;; Tagged symbols are only available on aarch64-linux-android.
+; RUN: not llc %s -mtriple=aarch64-linux-unknown
+; RUN: not llc %s -mtriple=x86_64-linux-unknown
+
+; RUN: llc %s -mtriple=aarch64-linux-android31 -o %t.S
+; RUN: FileCheck %s --input-file=%t.S --check-prefix=CHECK-ASM
+; RUN: llvm-mc -filetype=obj %t.S -triple=aarch64-linux-android31 -o %t.o
+; RUN: llvm-readelf -r %t.o | FileCheck %s --check-prefix=CHECK-RELOCS
+
+; RUN: obj2yaml %t.o -o %t.yaml
+; RUN: FileCheck %s --input-file=%t.yaml --check-prefix=CHECK-YAML
+; RUN: yaml2obj %t.yaml -o %t.o
+; RUN: llvm-readelf -r %t.o | FileCheck %s --check-prefix=CHECK-RELOCS
+
+; CHECK-RELOCS: Relocation section '.rela.memtag.globals.static' {{.*}} contains 4 entries
+; CHECK-RELOCS: R_AARCH64_NONE {{.*}} internal_four
+; CHECK-RELOCS: R_AARCH64_NONE {{.*}} four
+; CHECK-RELOCS: R_AARCH64_NONE {{.*}} sixteen
+; CHECK-RELOCS: R_AARCH64_NONE {{.*}} huge
+; CHECK-RELOCS-NOT: specialcaselisted
+
+; CHECK-YAML: Sections:
+; CHECK-YAML: - Name: .rela.memtag.globals.static
+; CHECK-YAML-NOT: - Name:
+; CHECK-YAML: Relocations:
+; CHECK-YAML-NEXT: - Symbol: internal_four
+; CHECK-YAML-NEXT: Type: R_AARCH64_NONE
+; CHECK-YAML-NEXT: - Symbol: four
+; CHECK-YAML-NEXT: Type: R_AARCH64_NONE
+; CHECK-YAML-NEXT: - Symbol: sixteen
+; CHECK-YAML-NEXT: Type: R_AARCH64_NONE
+; CHECK-YAML-NEXT: - Symbol: huge
+; CHECK-YAML-NEXT: Type: R_AARCH64_NONE
+; CHECK-YAML-NEXT: -
+
+; CHECK-ASM: .memtag internal_four
+; CHECK-ASM: .memtag four
+; CHECK-ASM: .memtag sixteen
+; CHECK-ASM: .memtag huge
+; CHECK-ASM-NOT: .memtag specialcaselisted
+
+ at internal_four = internal global i32 1, sanitize_memtag
+ at four = global i32 1, sanitize_memtag
+ at sixteen = global [16 x i8] zeroinitializer, sanitize_memtag
+ at huge = global [16777232 x i8] zeroinitializer, sanitize_memtag
+ at specialcaselisted = global i16 2
More information about the cfe-commits
mailing list