diff options
| author | Alex Shlyapnikov <alekseys@google.com> | 2018-03-23 17:57:54 +0000 |
|---|---|---|
| committer | Alex Shlyapnikov <alekseys@google.com> | 2018-03-23 17:57:54 +0000 |
| commit | 83e78414192f2270473b8d54e737b8b9f2af0477 (patch) | |
| tree | eabbc9dceadfa9a19876afb7a20b53a9b8e76bb8 /llvm/lib/Transforms | |
| parent | 41573804f278a6ff3bbc43217c6d4b3bb415df73 (diff) | |
| download | bcm5719-llvm-83e78414192f2270473b8d54e737b8b9f2af0477.tar.gz bcm5719-llvm-83e78414192f2270473b8d54e737b8b9f2af0477.zip | |
[HWASan] Port HWASan to Linux x86-64 (LLVM)
Summary:
Porting HWASan to Linux x86-64, first of the three patches, LLVM part.
The approach is similar to ARM case, trap signal is used to communicate
memory tag check failure. int3 instruction is used to generate a signal,
access parameters are stored in nop [eax + offset] instruction immediately
following the int3 one.
One notable difference is that x86-64 has to untag the pointer before use
due to the lack of feature comparable to ARM's TBI (Top Byte Ignore).
Reviewers: eugenis
Subscribers: kristof.beyls, llvm-commits
Differential Revision: https://reviews.llvm.org/D44699
llvm-svn: 328342
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp | 71 |
1 files changed, 58 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 21541fc9029..6365806d1f1 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -123,6 +123,7 @@ public: bool doInitialization(Module &M) override; void initializeCallbacks(Module &M); + void untagPointerOperand(Instruction *I, Value *Addr); void instrumentMemAccessInline(Value *PtrLong, bool IsWrite, unsigned AccessSizeIndex, Instruction *InsertBefore); @@ -145,6 +146,8 @@ public: private: LLVMContext *C; + Triple TargetTriple; + Type *IntptrTy; Type *Int8Ty; @@ -181,7 +184,7 @@ bool HWAddressSanitizer::doInitialization(Module &M) { DEBUG(dbgs() << "Init " << M.getName() << "\n"); auto &DL = M.getDataLayout(); - Triple TargetTriple(M.getTargetTriple()); + TargetTriple = Triple(M.getTargetTriple()); C = &(M.getContext()); IRBuilder<> IRB(*C); @@ -228,10 +231,10 @@ void HWAddressSanitizer::initializeCallbacks(Module &M) { } Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I, - bool *IsWrite, - uint64_t *TypeSize, - unsigned *Alignment, - Value **MaybeMask) { + bool *IsWrite, + uint64_t *TypeSize, + unsigned *Alignment, + Value **MaybeMask) { // Skip memory accesses inserted by another instrumentation. if (I->getMetadata("nosanitize")) return nullptr; @@ -281,17 +284,42 @@ Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I, return PtrOperand; } +static unsigned getPointerOperandIndex(Instruction *I) { + if (LoadInst *LI = dyn_cast<LoadInst>(I)) + return LI->getPointerOperandIndex(); + if (StoreInst *SI = dyn_cast<StoreInst>(I)) + return SI->getPointerOperandIndex(); + if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) + return RMW->getPointerOperandIndex(); + if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) + return XCHG->getPointerOperandIndex(); + report_fatal_error("Unexpected instruction"); + return -1; +} + static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { size_t Res = countTrailingZeros(TypeSize / 8); assert(Res < kNumberOfAccessSizes); return Res; } +void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) { + if (TargetTriple.isAArch64()) + return; + + IRBuilder<> IRB(I); + Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); + Value *UntaggedPtr = + IRB.CreateIntToPtr(untagPointer(IRB, AddrLong), Addr->getType()); + I->setOperand(getPointerOperandIndex(I), UntaggedPtr); +} + void HWAddressSanitizer::instrumentMemAccessInline(Value *PtrLong, bool IsWrite, unsigned AccessSizeIndex, Instruction *InsertBefore) { IRBuilder<> IRB(InsertBefore); - Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, kPointerTagShift), IRB.getInt8Ty()); + Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, kPointerTagShift), + IRB.getInt8Ty()); Value *AddrLong = untagPointer(IRB, PtrLong); Value *ShadowLong = IRB.CreateLShr(AddrLong, kShadowScale); if (ClMappingOffset) @@ -307,13 +335,29 @@ void HWAddressSanitizer::instrumentMemAccessInline(Value *PtrLong, bool IsWrite, MDBuilder(*C).createBranchWeights(1, 100000)); IRB.SetInsertPoint(CheckTerm); - // The signal handler will find the data address in x0. - InlineAsm *Asm = InlineAsm::get( - FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), - "brk #" + - itostr(0x900 + Recover * 0x20 + IsWrite * 0x10 + AccessSizeIndex), - "{x0}", - /*hasSideEffects=*/true); + const int64_t AccessInfo = Recover * 0x20 + IsWrite * 0x10 + AccessSizeIndex; + InlineAsm *Asm; + switch (TargetTriple.getArch()) { + case Triple::x86_64: + // The signal handler will find the data address in rdi. + Asm = InlineAsm::get( + FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), + "int3\nnopl " + itostr(0x40 + AccessInfo) + "(%rax)", + "{rdi}", + /*hasSideEffects=*/true); + break; + case Triple::aarch64: + case Triple::aarch64_be: + // The signal handler will find the data address in x0. + Asm = InlineAsm::get( + FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), + "brk #" + itostr(0x900 + AccessInfo), + "{x0}", + /*hasSideEffects=*/true); + break; + default: + report_fatal_error("unsupported architecture"); + } IRB.CreateCall(Asm, PtrLong); } @@ -349,6 +393,7 @@ bool HWAddressSanitizer::instrumentMemAccess(Instruction *I) { IRB.CreateCall(HwasanMemoryAccessCallbackSized[IsWrite], {AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8)}); } + untagPointerOperand(I, Addr); return true; } |

