This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG850defb86164: Add assembler plumbing for sanitize_memtag 
(authored by hctim).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128958/new/

https://reviews.llvm.org/D128958

Files:
  clang/test/Driver/memtag-stack.c
  clang/test/Driver/memtag-stack_lto.c
  clang/test/Driver/memtag_lto.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
  llvm/test/MC/AArch64/global-tagging.ll

Index: llvm/test/MC/AArch64/global-tagging.ll
===================================================================
--- /dev/null
+++ 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
+
+@internal_four = internal global i32 1, sanitize_memtag
+@four = global i32 1, sanitize_memtag
+@sixteen = global [16 x i8] zeroinitializer, sanitize_memtag
+@huge = global [16777232 x i8] zeroinitializer, sanitize_memtag
+@specialcaselisted = global i16 2
Index: llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
===================================================================
--- llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -34,6 +34,8 @@
 
   ~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 @@
   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);
Index: llvm/lib/MC/MCSymbolELF.cpp
===================================================================
--- llvm/lib/MC/MCSymbolELF.cpp
+++ llvm/lib/MC/MCSymbolELF.cpp
@@ -33,7 +33,10 @@
   ELF_WeakrefUsedInReloc_Shift = 11,
 
   // One bit.
-  ELF_BindingSet_Shift = 12
+  ELF_BindingSet_Shift = 12,
+
+  // One bit.
+  ELF_IsMemoryTagged_Shift = 13,
 };
 }
 
@@ -193,4 +196,16 @@
 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);
+}
 }
Index: llvm/lib/MC/MCParser/AsmParser.cpp
===================================================================
--- llvm/lib/MC/MCParser/AsmParser.cpp
+++ llvm/lib/MC/MCParser/AsmParser.cpp
@@ -539,6 +539,7 @@
     DK_LTO_DISCARD,
     DK_LTO_SET_CONDITIONAL,
     DK_CFI_MTE_TAGGED_FRAME,
+    DK_MEMTAG,
     DK_END
   };
 
@@ -2298,6 +2299,8 @@
       return parseDirectivePseudoProbe();
     case DK_LTO_DISCARD:
       return parseDirectiveLTODiscard();
+    case DK_MEMTAG:
+      return parseDirectiveSymbolAttribute(MCSA_Memtag);
     }
 
     return Error(IDLoc, "unknown directive");
@@ -4984,8 +4987,9 @@
 
     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 @@
   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) {
Index: llvm/lib/MC/MCMachOStreamer.cpp
===================================================================
--- llvm/lib/MC/MCMachOStreamer.cpp
+++ llvm/lib/MC/MCMachOStreamer.cpp
@@ -358,6 +358,7 @@
   case MCSA_Local:
   case MCSA_LGlobal:
   case MCSA_Exported:
+  case MCSA_Memtag:
     return false;
 
   case MCSA_Global:
Index: llvm/lib/MC/MCELFStreamer.cpp
===================================================================
--- llvm/lib/MC/MCELFStreamer.cpp
+++ llvm/lib/MC/MCELFStreamer.cpp
@@ -287,6 +287,10 @@
     Symbol->setVisibility(ELF::STV_PROTECTED);
     break;
 
+  case MCSA_Memtag:
+    Symbol->setMemtag(true);
+    break;
+
   case MCSA_Hidden:
     Symbol->setVisibility(ELF::STV_HIDDEN);
     break;
Index: llvm/lib/MC/MCAsmStreamer.cpp
===================================================================
--- llvm/lib/MC/MCAsmStreamer.cpp
+++ llvm/lib/MC/MCAsmStreamer.cpp
@@ -769,6 +769,9 @@
   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);
Index: llvm/lib/MC/ELFObjectWriter.cpp
===================================================================
--- llvm/lib/MC/ELFObjectWriter.cpp
+++ llvm/lib/MC/ELFObjectWriter.cpp
@@ -192,6 +192,8 @@
   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 @@
   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 @@
       Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
   StringTableIndex = addToSectionTable(StrtabSection);
 
+  createMemtagRelocs(Asm);
+
   RevGroupMapTy RevGroupMap;
   SectionIndexMapTy SectionIndexMap;
 
@@ -1317,6 +1338,15 @@
   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:
Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -712,6 +712,16 @@
   // 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;
 
Index: llvm/include/llvm/MC/MCSymbolELF.h
===================================================================
--- llvm/include/llvm/MC/MCSymbolELF.h
+++ llvm/include/llvm/MC/MCSymbolELF.h
@@ -43,6 +43,9 @@
   void setIsSignature() const;
   bool isSignature() const;
 
+  void setMemtag(bool Tagged);
+  bool isMemtag() const;
+
   static bool classof(const MCSymbol *S) { return S->isELF(); }
 
 private:
Index: llvm/include/llvm/MC/MCELFObjectWriter.h
===================================================================
--- llvm/include/llvm/MC/MCELFObjectWriter.h
+++ llvm/include/llvm/MC/MCELFObjectWriter.h
@@ -139,6 +139,14 @@
   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.
Index: llvm/include/llvm/MC/MCDirectives.h
===================================================================
--- llvm/include/llvm/MC/MCDirectives.h
+++ llvm/include/llvm/MC/MCDirectives.h
@@ -45,7 +45,8 @@
   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 {
Index: llvm/include/llvm/MC/MCAsmInfo.h
===================================================================
--- llvm/include/llvm/MC/MCAsmInfo.h
+++ llvm/include/llvm/MC/MCAsmInfo.h
@@ -442,6 +442,8 @@
   /// 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 @@
     return ProtectedVisibilityAttr;
   }
 
+  MCSymbolAttr getMemtagAttr() const { return MemtagAttr; }
+
   bool doesSupportDebugInformation() const { return SupportsDebugInformation; }
 
   ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; }
Index: llvm/include/llvm/BinaryFormat/ELF.h
===================================================================
--- llvm/include/llvm/BinaryFormat/ELF.h
+++ llvm/include/llvm/BinaryFormat/ELF.h
@@ -1035,6 +1035,10 @@
   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
Index: clang/test/Driver/memtag-stack_lto.c
===================================================================
--- clang/test/Driver/memtag-stack_lto.c
+++ 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 \
Index: clang/test/Driver/memtag-stack.c
===================================================================
--- clang/test/Driver/memtag-stack.c
+++ 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
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to