hctim updated this revision to Diff 434618.
hctim marked 5 inline comments as done.
hctim added a comment.
Update w/ Vitaly's comments.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D126100/new/
https://reviews.llvm.org/D126100
Files:
llvm/include/llvm/AsmParser/LLParser.h
llvm/include/llvm/AsmParser/LLToken.h
llvm/include/llvm/IR/GlobalValue.h
llvm/lib/AsmParser/LLLexer.cpp
llvm/lib/AsmParser/LLParser.cpp
llvm/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
llvm/lib/IR/AsmWriter.cpp
llvm/lib/IR/Globals.cpp
llvm/lib/IR/LLVMContextImpl.h
llvm/test/Assembler/globalvariable-attributes.ll
llvm/test/Bitcode/compatibility.ll
Index: llvm/test/Bitcode/compatibility.ll
===================================================================
--- llvm/test/Bitcode/compatibility.ll
+++ llvm/test/Bitcode/compatibility.ll
@@ -203,6 +203,16 @@
@llvm.global_dtors = appending global [1 x %pri.func.data] [%pri.func.data { i32 0, void ()* @g.f1, i8* @g.used3 }], section "llvm.metadata"
; CHECK: @llvm.global_dtors = appending global [1 x %pri.func.data] [%pri.func.data { i32 0, void ()* @g.f1, i8* @g.used3 }], section "llvm.metadata"
+; Global Variables -- sanitizers
[email protected]_sanitize = global i32 0, no_sanitize
[email protected]_sanitize_address = global i32 0, no_sanitize_address
[email protected]_sanitize_hwaddress = global i32 0, no_sanitize_hwaddress
[email protected]_address_dyninit = global i32 0, sanitize_address_dyninit
+; CHECK: @g.no_sanitize = global i32 0, no_sanitize
+; CHECK: @g.no_sanitize_address = global i32 0, no_sanitize_address
+; CHECK: @g.no_sanitize_hwaddress = global i32 0, no_sanitize_hwaddress
+; CHECK: @g.sanitize_address_dyninit = global i32 0, sanitize_address_dyninit
+
;; Aliases
; Format: @<Name> = [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal]
; [unnamed_addr] alias <AliaseeTy> @<Aliasee>
Index: llvm/test/Assembler/globalvariable-attributes.ll
===================================================================
--- llvm/test/Assembler/globalvariable-attributes.ll
+++ llvm/test/Assembler/globalvariable-attributes.ll
@@ -4,6 +4,11 @@
@g2 = global i32 2, align 4 "key3" = "value3"
@g3 = global i32 2 #0
@g4 = global i32 2, align 4 "key5" = "value5" #0
+@g5 = global i32 2, no_sanitize, align 4
+@g6 = global i32 2, no_sanitize_address, align 4
+@g7 = global i32 2, no_sanitize_hwaddress, align 4
+@g8 = global i32 2, no_sanitize_address, no_sanitize_hwaddress, align 4
+@g9 = global i32 2, no_sanitize, no_sanitize_address, no_sanitize_hwaddress, align 4
attributes #0 = { "string" = "value" nobuiltin norecurse }
@@ -11,6 +16,15 @@
; CHECK: @g2 = global i32 2, align 4 #1
; CHECK: @g3 = global i32 2 #2
; CHECK: @g4 = global i32 2, align 4 #3
+; CHECK: @g5 = global i32 2, no_sanitize, align 4
+; CHECK: @g6 = global i32 2, no_sanitize_address, align 4
+; CHECK: @g7 = global i32 2, no_sanitize_hwaddress, align 4
+; CHECK: @g8 = global i32 2, no_sanitize_address, no_sanitize_hwaddress, align 4
+
+;; no_sanitize attribute should override and turncate other sanitize_* attrs.
+; CHECK: @g9 = global i32 2, no_sanitize, align 4
+; CHECK-NOT: no_sanitize_address
+; CHECK-NOT: no_sanitize_hwaddress
; CHECK: attributes #0 = { "key"="value" "key2"="value2" }
; CHECK: attributes #1 = { "key3"="value3" }
Index: llvm/lib/IR/LLVMContextImpl.h
===================================================================
--- llvm/lib/IR/LLVMContextImpl.h
+++ llvm/lib/IR/LLVMContextImpl.h
@@ -1503,6 +1503,9 @@
/// Collection of per-GlobalValue partitions used in this context.
DenseMap<const GlobalValue *, StringRef> GlobalValuePartitions;
+ DenseMap<const GlobalValue *, GlobalValue::SanitizerMetadata>
+ GlobalValueSanitizerMetadata;
+
/// DiscriminatorTable - This table maps file:line locations to an
/// integer representing the next DWARF path discriminator to assign to
/// instructions in different blocks at the same location.
Index: llvm/lib/IR/Globals.cpp
===================================================================
--- llvm/lib/IR/Globals.cpp
+++ llvm/lib/IR/Globals.cpp
@@ -67,6 +67,8 @@
setDLLStorageClass(Src->getDLLStorageClass());
setDSOLocal(Src->isDSOLocal());
setPartition(Src->getPartition());
+ if (Src->hasSanitizerMetadata())
+ setSanitizerMetadata(Src->getSanitizerMetadata());
}
void GlobalValue::removeFromParent() {
@@ -217,6 +219,18 @@
HasPartition = !S.empty();
}
+using SanitizerMetadata = GlobalValue::SanitizerMetadata;
+const SanitizerMetadata &GlobalValue::getSanitizerMetadata() const {
+ assert(hasSanitizerMetadata());
+ assert(getContext().pImpl->GlobalValueSanitizerMetadata.count(this));
+ return getContext().pImpl->GlobalValueSanitizerMetadata[this];
+}
+
+void GlobalValue::setSanitizerMetadata(const SanitizerMetadata &Meta) {
+ getContext().pImpl->GlobalValueSanitizerMetadata[this] = Meta;
+ HasSanitizerMetadata = true;
+}
+
StringRef GlobalObject::getSectionImpl() const {
assert(hasSection());
return getContext().pImpl->GlobalObjectSections[this];
Index: llvm/lib/IR/AsmWriter.cpp
===================================================================
--- llvm/lib/IR/AsmWriter.cpp
+++ llvm/lib/IR/AsmWriter.cpp
@@ -3537,6 +3537,21 @@
Out << '"';
}
+ using SanitizerMetadata = llvm::GlobalValue::SanitizerMetadata;
+ if (GV->hasSanitizerMetadata()) {
+ SanitizerMetadata MD = GV->getSanitizerMetadata();
+ if (MD.NoSanitize) {
+ Out << ", no_sanitize";
+ } else {
+ if (MD.NoAddress)
+ Out << ", no_sanitize_address";
+ if (MD.NoHWAddress)
+ Out << ", no_sanitize_hwaddress";
+ if (MD.IsDynInit)
+ Out << ", sanitize_address_dyninit";
+ }
+ }
+
maybePrintComdat(Out, *GV);
if (MaybeAlign A = GV->getAlign())
Out << ", align " << A->value();
Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
===================================================================
--- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1344,7 +1344,7 @@
// GLOBALVAR: [strtab offset, strtab size, type, isconst, initid,
// linkage, alignment, section, visibility, threadlocal,
// unnamed_addr, externally_initialized, dllstorageclass,
- // comdat, attributes, DSO_Local]
+ // comdat, attributes, DSO_Local, GlobalSanitizer]
Vals.push_back(addToStrtab(GV.getName()));
Vals.push_back(GV.getName().size());
Vals.push_back(VE.getTypeID(GV.getValueType()));
@@ -1360,10 +1360,8 @@
GV.getUnnamedAddr() != GlobalValue::UnnamedAddr::None ||
GV.isExternallyInitialized() ||
GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass ||
- GV.hasComdat() ||
- GV.hasAttributes() ||
- GV.isDSOLocal() ||
- GV.hasPartition()) {
+ GV.hasComdat() || GV.hasAttributes() || GV.isDSOLocal() ||
+ GV.hasPartition() || GV.hasSanitizerMetadata()) {
Vals.push_back(getEncodedVisibility(GV));
Vals.push_back(getEncodedThreadLocalMode(GV));
Vals.push_back(getEncodedUnnamedAddr(GV));
@@ -1377,6 +1375,11 @@
Vals.push_back(GV.isDSOLocal());
Vals.push_back(addToStrtab(GV.getPartition()));
Vals.push_back(GV.getPartition().size());
+
+ if (GV.hasSanitizerMetadata())
+ Vals.push_back(GV.getSanitizerMetadata().serialize());
+ else
+ Vals.push_back(UINT_MAX);
} else {
AbbrevToUse = SimpleGVarAbbrev;
}
Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp
===================================================================
--- llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -3540,6 +3540,12 @@
if (Record.size() > 15)
NewGV->setPartition(StringRef(Strtab.data() + Record[14], Record[15]));
+ if (Record.size() > 16 && Record[16] != UINT_MAX) {
+ llvm::GlobalValue::SanitizerMetadata Meta;
+ Meta.deserialize(Record[16]);
+ NewGV->setSanitizerMetadata(Meta);
+ }
+
return Error::success();
}
Index: llvm/lib/AsmParser/LLParser.cpp
===================================================================
--- llvm/lib/AsmParser/LLParser.cpp
+++ llvm/lib/AsmParser/LLParser.cpp
@@ -1103,6 +1103,45 @@
return false;
}
+static bool isSanitizer(lltok::Kind Kind) {
+ switch (Kind) {
+ case lltok::kw_no_sanitize:
+ case lltok::kw_no_sanitize_address:
+ case lltok::kw_no_sanitize_hwaddress:
+ case lltok::kw_sanitize_address_dyninit:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool LLParser::parseSanitizer(GlobalVariable *GV) {
+ using SanitizerMetadata = GlobalValue::SanitizerMetadata;
+ SanitizerMetadata Meta;
+ if (GV->hasSanitizerMetadata())
+ Meta = GV->getSanitizerMetadata();
+
+ switch (Lex.getKind()) {
+ case lltok::kw_no_sanitize:
+ Meta.NoSanitize = true;
+ break;
+ case lltok::kw_no_sanitize_address:
+ Meta.NoAddress = true;
+ break;
+ case lltok::kw_no_sanitize_hwaddress:
+ Meta.NoHWAddress = true;
+ break;
+ case lltok::kw_sanitize_address_dyninit:
+ Meta.IsDynInit = true;
+ break;
+ default:
+ return tokError("non-sanitizer token passed to LLParser::parseSanitizer()");
+ }
+ GV->setSanitizerMetadata(Meta);
+ Lex.Lex();
+ return false;
+}
+
/// parseGlobal
/// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier
/// OptionalVisibility OptionalDLLStorageClass
@@ -1221,6 +1260,9 @@
} else if (Lex.getKind() == lltok::MetadataVar) {
if (parseGlobalObjectMetadataAttachment(*GV))
return true;
+ } else if (isSanitizer(Lex.getKind())) {
+ if (parseSanitizer(GV))
+ return true;
} else {
Comdat *C;
if (parseOptionalComdat(Name, C))
Index: llvm/lib/AsmParser/LLLexer.cpp
===================================================================
--- llvm/lib/AsmParser/LLLexer.cpp
+++ llvm/lib/AsmParser/LLLexer.cpp
@@ -580,6 +580,12 @@
KEYWORD(prefix);
KEYWORD(prologue);
+ // Sanitizer keywords.
+ KEYWORD(no_sanitize);
+ KEYWORD(no_sanitize_address);
+ KEYWORD(no_sanitize_hwaddress);
+ KEYWORD(sanitize_address_dyninit);
+
KEYWORD(ccc);
KEYWORD(fastcc);
KEYWORD(coldcc);
Index: llvm/include/llvm/IR/GlobalValue.h
===================================================================
--- llvm/include/llvm/IR/GlobalValue.h
+++ llvm/include/llvm/IR/GlobalValue.h
@@ -79,14 +79,15 @@
ValueType(Ty), Visibility(DefaultVisibility),
UnnamedAddrVal(unsigned(UnnamedAddr::None)),
DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal),
- HasLLVMReservedName(false), IsDSOLocal(false), HasPartition(false) {
+ HasLLVMReservedName(false), IsDSOLocal(false), HasPartition(false),
+ HasSanitizerMetadata(false) {
setLinkage(Linkage);
setName(Name);
}
Type *ValueType;
- static const unsigned GlobalValueSubClassDataBits = 16;
+ static const unsigned GlobalValueSubClassDataBits = 15;
// All bitfields use unsigned as the underlying type so that MSVC will pack
// them.
@@ -111,9 +112,14 @@
/// https://lld.llvm.org/Partitions.html).
unsigned HasPartition : 1;
+ /// True if this symbol has sanitizer metadata available. Should only happen
+ /// if sanitizers were enabled when building the translation unit which
+ /// contains this GV.
+ unsigned HasSanitizerMetadata : 1;
+
private:
// Give subclasses access to what otherwise would be wasted padding.
- // (16 + 4 + 2 + 2 + 2 + 3 + 1 + 1 + 1) == 32.
+ // (15 + 4 + 2 + 2 + 2 + 3 + 1 + 1 + 1 + 1) == 32.
unsigned SubClassData : GlobalValueSubClassDataBits;
friend class Constant;
@@ -288,6 +294,53 @@
StringRef getPartition() const;
void setPartition(StringRef Part);
+ // ASan, HWASan and Memtag sanitizers have some instrumentation that applies
+ // specifically to global variables. This instrumentation is implicitly
+ // applied to all global variables when built with -fsanitize=*. What we need
+ // is a way to persist the information that a certain global variable should
+ // *not* have sanitizers applied, which occurs if:
+ // 1. The global variable is in the sanitizer ignore list, or
+ // 2. The global variable is created by the sanitizers itself for internal
+ // usage, or
+ // 3. The global variable has __attribute__((no_sanitize("..."))) or
+ // __attribute__((disable_sanitizer_instrumentation)).
+ //
+ // This is important, a some IR passes like GlobalMerge can delete global
+ // variables and replace them with new ones. If the old variables were marked
+ // to be unsanitized, then the new ones should also be.
+ struct SanitizerMetadata {
+ SanitizerMetadata()
+ : NoSanitize(false), NoAddress(false), NoHWAddress(false),
+ NoMemtag(false), IsDynInit(false) {}
+ unsigned NoSanitize : 1;
+ unsigned NoAddress : 1;
+ unsigned NoHWAddress : 1;
+ unsigned NoMemtag : 1;
+
+ // ASan-specific metadata. Is this global variable dynamically initialized
+ // (from a C++ language perspective), and should therefore be checked for
+ // ODR violations.
+ unsigned IsDynInit : 1;
+
+ unsigned serialize() const {
+ return NoSanitize | (NoAddress << 1) | (NoHWAddress << 2) |
+ (NoMemtag << 3) | (IsDynInit << 4);
+ }
+ void deserialize(unsigned V) {
+ if (V & (1 << 0)) NoSanitize = true;
+ if (V & (1 << 1)) NoAddress = true;
+ if (V & (1 << 2)) NoHWAddress = true;
+ if (V & (1 << 3)) NoMemtag = true;
+ if (V & (1 << 4)) IsDynInit = true;
+ }
+ };
+ static_assert(sizeof(SanitizerMetadata) <= sizeof(unsigned),
+ "Sanitizer Metadata is too large for naive serialization.");
+
+ bool hasSanitizerMetadata() const { return HasSanitizerMetadata; }
+ const SanitizerMetadata &getSanitizerMetadata() const;
+ void setSanitizerMetadata(const SanitizerMetadata &Meta);
+
static LinkageTypes getLinkOnceLinkage(bool ODR) {
return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage;
}
Index: llvm/include/llvm/AsmParser/LLToken.h
===================================================================
--- llvm/include/llvm/AsmParser/LLToken.h
+++ llvm/include/llvm/AsmParser/LLToken.h
@@ -392,6 +392,17 @@
kw_bit,
kw_varFlags,
+ // Extra sanitizer attributes that are used for global variables (GV's).
+ // GV's mentioned in -fsanitize-ignorelist=<file>.
+ kw_no_sanitize,
+ // GV's with __attribute__((no_sanitize("address"))).
+ kw_no_sanitize_address,
+ // GV's where the clang++ frontend (when ASan is used) notes that this is
+ // dynamically initialized, and thus needs ODR detection.
+ kw_sanitize_address_dyninit,
+ // GV's with __attribute__((no_sanitize("hwaddress"))).
+ kw_no_sanitize_hwaddress,
+
// Unsigned Valued tokens (UIntVal).
LabelID, // 42:
GlobalID, // @42
Index: llvm/include/llvm/AsmParser/LLParser.h
===================================================================
--- llvm/include/llvm/AsmParser/LLParser.h
+++ llvm/include/llvm/AsmParser/LLParser.h
@@ -514,6 +514,7 @@
bool parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts,
Optional<unsigned> *InRangeOp = nullptr);
bool parseOptionalComdat(StringRef GlobalName, Comdat *&C);
+ bool parseSanitizer(GlobalVariable *GV);
bool parseMetadataAsValue(Value *&V, PerFunctionState &PFS);
bool parseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg,
PerFunctionState *PFS);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits