hctim updated this revision to Diff 478367.
hctim marked an inline comment as done.
hctim added a comment.
Update comment for .memtag globals when generating object files on
non-MTE-globals supported architectures, and move said comment from an assert
to a fatal error.
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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits