[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