Skip to content

Commit

Permalink
Hardware-assisted AddressSanitizer (llvm part).
Browse files Browse the repository at this point in the history
Summary:
This is LLVM instrumentation for the new HWASan tool. It is basically
a stripped down copy of ASan at this point, w/o stack or global
support. Instrumenation adds a global constructor + runtime callbacks
for every load and store.

HWASan comes with its own IR attribute.

A brief design document can be found in
clang/docs/HardwareAssistedAddressSanitizerDesign.rst (submitted earlier).

Reviewers: kcc, pcc, alekseyshl

Subscribers: srhines, mehdi_amini, mgorny, javed.absar, eraman, llvm-commits, hiraditya

Differential Revision: https://reviews.llvm.org/D40932

llvm-svn: 320217
  • Loading branch information
eugenis committed Dec 9, 2017
1 parent 8bd9d6a commit c667c1f
Show file tree
Hide file tree
Showing 30 changed files with 676 additions and 17 deletions.
1 change: 1 addition & 0 deletions llvm/docs/BitCodeFormat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,7 @@ The integer codes are mapped to well-known attributes as follows.
* code 52: ``writeonly``
* code 53: ``speculatable``
* code 54: ``strictfp``
* code 55: ``sanitize_hwaddress``

.. note::
The ``allocsize`` attribute has a special encoding for its arguments. Its two
Expand Down
4 changes: 4 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1597,6 +1597,10 @@ example:
``sanitize_thread``
This attribute indicates that ThreadSanitizer checks
(dynamic thread safety analysis) are enabled for this function.
``sanitize_hwaddress``
This attribute indicates that HWAddressSanitizer checks
(dynamic address safety analysis based on tagged pointers) are enabled for
this function.
``speculatable``
This function attribute indicates that the function does not have any
effects besides calculating its result and does not have undefined behavior.
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ enum AttributeKindCodes {
ATTR_KIND_WRITEONLY = 52,
ATTR_KIND_SPECULATABLE = 53,
ATTR_KIND_STRICT_FP = 54,
ATTR_KIND_SANITIZE_HWADDRESS = 55,
};

enum ComdatSelectionKindCodes {
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/Attributes.td
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ def SanitizeThread : EnumAttr<"sanitize_thread">;
/// MemorySanitizer is on.
def SanitizeMemory : EnumAttr<"sanitize_memory">;

/// HWAddressSanitizer is on.
def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress">;

/// Argument is swift error.
def SwiftError : EnumAttr<"swifterror">;

Expand Down Expand Up @@ -200,6 +203,7 @@ class CompatRule<string F> {
def : CompatRule<"isEqual<SanitizeAddressAttr>">;
def : CompatRule<"isEqual<SanitizeThreadAttr>">;
def : CompatRule<"isEqual<SanitizeMemoryAttr>">;
def : CompatRule<"isEqual<SanitizeHWAddressAttr>">;
def : CompatRule<"isEqual<SafeStackAttr>">;

class MergeRule<string F> {
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/InitializePasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ void initializeStripNonDebugSymbolsPass(PassRegistry&);
void initializeStripNonLineTableDebugInfoPass(PassRegistry&);
void initializeStripSymbolsPass(PassRegistry&);
void initializeStructurizeCFGPass(PassRegistry&);
void initializeHWAddressSanitizerPass(PassRegistry&);
void initializeTailCallElimPass(PassRegistry&);
void initializeTailDuplicatePassPass(PassRegistry&);
void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&);
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/Transforms/Instrumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ ModulePass *createAddressSanitizerModulePass(bool CompileKernel = false,
FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0,
bool Recover = false);

FunctionPass *createHWAddressSanitizerPass();

// Insert ThreadSanitizer (race detection) instrumentation
FunctionPass *createThreadSanitizerPass();

Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,10 @@ unsigned MemoryDependenceResults::getLoadLoadClobberFullWidthSize(
return 0;

if (LIOffs + NewLoadByteSize > MemLocEnd &&
LI->getParent()->getParent()->hasFnAttribute(
Attribute::SanitizeAddress))
(LI->getParent()->getParent()->hasFnAttribute(
Attribute::SanitizeAddress) ||
LI->getParent()->getParent()->hasFnAttribute(
Attribute::SanitizeHWAddress)))
// We will be reading past the location accessed by the original program.
// While this is safe in a regular build, Address Safety analysis tools
// may start reporting false warnings. So, don't do widening.
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3511,7 +3511,8 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V,
// Speculative load may create a race that did not exist in the source.
LI->getFunction()->hasFnAttribute(Attribute::SanitizeThread) ||
// Speculative load may load data from dirty regions.
LI->getFunction()->hasFnAttribute(Attribute::SanitizeAddress))
LI->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
LI->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
return false;
const DataLayout &DL = LI->getModule()->getDataLayout();
return isDereferenceableAndAlignedPointer(LI->getPointerOperand(),
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(strictfp);
KEYWORD(safestack);
KEYWORD(sanitize_address);
KEYWORD(sanitize_hwaddress);
KEYWORD(sanitize_thread);
KEYWORD(sanitize_memory);
KEYWORD(swifterror);
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,8 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break;
case lltok::kw_sanitize_address:
B.addAttribute(Attribute::SanitizeAddress); break;
case lltok::kw_sanitize_hwaddress:
B.addAttribute(Attribute::SanitizeHWAddress); break;
case lltok::kw_sanitize_thread:
B.addAttribute(Attribute::SanitizeThread); break;
case lltok::kw_sanitize_memory:
Expand Down Expand Up @@ -1468,6 +1470,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) {
case lltok::kw_optsize:
case lltok::kw_returns_twice:
case lltok::kw_sanitize_address:
case lltok::kw_sanitize_hwaddress:
case lltok::kw_sanitize_memory:
case lltok::kw_sanitize_thread:
case lltok::kw_ssp:
Expand Down Expand Up @@ -1560,6 +1563,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) {
case lltok::kw_optsize:
case lltok::kw_returns_twice:
case lltok::kw_sanitize_address:
case lltok::kw_sanitize_hwaddress:
case lltok::kw_sanitize_memory:
case lltok::kw_sanitize_thread:
case lltok::kw_ssp:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ enum Kind {
kw_alwaysinline,
kw_argmemonly,
kw_sanitize_address,
kw_sanitize_hwaddress,
kw_builtin,
kw_byval,
kw_inalloca,
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,7 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) {
case Attribute::WriteOnly: return 1ULL << 53;
case Attribute::Speculatable: return 1ULL << 54;
case Attribute::StrictFP: return 1ULL << 55;
case Attribute::SanitizeHWAddress: return 1ULL << 56;
case Attribute::Dereferenceable:
llvm_unreachable("dereferenceable attribute not supported in raw format");
break;
Expand Down Expand Up @@ -1368,6 +1369,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
return Attribute::StructRet;
case bitc::ATTR_KIND_SANITIZE_ADDRESS:
return Attribute::SanitizeAddress;
case bitc::ATTR_KIND_SANITIZE_HWADDRESS:
return Attribute::SanitizeHWAddress;
case bitc::ATTR_KIND_SANITIZE_THREAD:
return Attribute::SanitizeThread;
case bitc::ATTR_KIND_SANITIZE_MEMORY:
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
return bitc::ATTR_KIND_STRUCT_RET;
case Attribute::SanitizeAddress:
return bitc::ATTR_KIND_SANITIZE_ADDRESS;
case Attribute::SanitizeHWAddress:
return bitc::ATTR_KIND_SANITIZE_HWADDRESS;
case Attribute::SanitizeThread:
return bitc::ATTR_KIND_SANITIZE_THREAD;
case Attribute::SanitizeMemory:
Expand Down
21 changes: 11 additions & 10 deletions llvm/lib/CodeGen/ShrinkWrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,16 +558,17 @@ bool ShrinkWrap::isShrinkWrapEnabled(const MachineFunction &MF) {
switch (EnableShrinkWrapOpt) {
case cl::BOU_UNSET:
return TFI->enableShrinkWrapping(MF) &&
// Windows with CFI has some limitations that make it impossible
// to use shrink-wrapping.
!MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
// Sanitizers look at the value of the stack at the location
// of the crash. Since a crash can happen anywhere, the
// frame must be lowered before anything else happen for the
// sanitizers to be able to get a correct stack frame.
!(MF.getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
MF.getFunction()->hasFnAttribute(Attribute::SanitizeThread) ||
MF.getFunction()->hasFnAttribute(Attribute::SanitizeMemory));
// Windows with CFI has some limitations that make it impossible
// to use shrink-wrapping.
!MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
// Sanitizers look at the value of the stack at the location
// of the crash. Since a crash can happen anywhere, the
// frame must be lowered before anything else happen for the
// sanitizers to be able to get a correct stack frame.
!(MF.getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
MF.getFunction()->hasFnAttribute(Attribute::SanitizeThread) ||
MF.getFunction()->hasFnAttribute(Attribute::SanitizeMemory) ||
MF.getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress));
// If EnableShrinkWrap is set, it takes precedence on whatever the
// target sets. The rational is that we assume we want to test
// something related to shrink-wrapping.
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/IR/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {

if (hasAttribute(Attribute::SanitizeAddress))
return "sanitize_address";
if (hasAttribute(Attribute::SanitizeHWAddress))
return "sanitize_hwaddress";
if (hasAttribute(Attribute::AlwaysInline))
return "alwaysinline";
if (hasAttribute(Attribute::ArgMemOnly))
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1375,6 +1375,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
case Attribute::NonLazyBind:
case Attribute::ReturnsTwice:
case Attribute::SanitizeAddress:
case Attribute::SanitizeHWAddress:
case Attribute::SanitizeThread:
case Attribute::SanitizeMemory:
case Attribute::MinSize:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ static Attribute::AttrKind parseAttrKind(StringRef Kind) {
.Case("returns_twice", Attribute::ReturnsTwice)
.Case("safestack", Attribute::SafeStack)
.Case("sanitize_address", Attribute::SanitizeAddress)
.Case("sanitize_hwaddress", Attribute::SanitizeHWAddress)
.Case("sanitize_memory", Attribute::SanitizeMemory)
.Case("sanitize_thread", Attribute::SanitizeThread)
.Case("ssp", Attribute::StackProtect)
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3607,7 +3607,8 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
case Intrinsic::lifetime_start:
// Asan needs to poison memory to detect invalid access which is possible
// even for empty lifetime range.
if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress))
if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
II->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
break;

if (removeTriviallyEmptyRange(*II, Intrinsic::lifetime_start,
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Instrumentation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ add_llvm_library(LLVMInstrumentation
SanitizerCoverage.cpp
ThreadSanitizer.cpp
EfficiencySanitizer.cpp
HWAddressSanitizer.cpp

ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms
Expand Down
Loading

0 comments on commit c667c1f

Please sign in to comment.